5 // define network constants
6 #define MAC_DAVID { 0x90, 0xA2, 0xDA, 0x0D, 0xF4, 0x63 }
7 #define MAC_PANIK { 0x90, 0xA2, 0xDA, 0x00, 0x9A, 0x94 }
8 #define MAC_PANIK2 { 0x90, 0xA2, 0xDA, 0x0E, 0xF3, 0x77 }
9 #define MAC_ADDRESS MAC_PANIK
12 // include Arduino libraries
18 // include third party libraries
19 #include "WebServer.h"
21 // include in-house libs
22 #include "PanikSwitch.h" // contains variable types for panik switch
24 // define SD and Ethernet select ports
26 #define ETHERNET_SELECT 10
28 // define machine variables
29 #define DEBOUNCE_TRESHOLD 10 // 10 milliseconds
30 #define ABORT_TRESHOLD 3000L // 3 seconds
31 #define PULSE_TRESHOLD 50 // 50 milliseconds
32 #define BLINK_TRESHOLD 100 // 100 milliseconds
35 #define RELAY_BUTTON_LEDS 5 // Button LED indicator
36 #define RELAY_GREEN_LEDS 6 // ``Non-Stop`` LED indicator
37 #define RELAY_RED_LEDS 8 // ``Studio 1`` LED indicator
38 #define RELAY_YELLOW_LEDS 7 // ``Studio 2`` LED indicator
40 #define RELAY_NONSTOP_OR_STUD 4 // Relay : Non-stop or Studio
41 #define RELAY_STUD1_OR_STUD2 9 // Relay : Studio 1 or Studio 2
44 #define BUTTON1 2 // ``Select`` button
45 #define BUTTON2 3 // ``Confirm`` button
46 #define NONSTOP_VIA_STUD1 14 // is nonstop coming out of studio 1
47 #define NONSTOP_VIA_STUD2 15 // is nonstop coming out of studio 2
51 /* define an array with led pins,
52 indexes in that array correspond to the values of possible selections
53 i.e.: RELAY_GREEN_LEDS: nonstop, RELAY_RED_LEDS: studio1, RELAY_YELLOW_LEDS: studio2
55 const int ledsArray[] = { RELAY_GREEN_LEDS, RELAY_RED_LEDS, RELAY_YELLOW_LEDS };
58 /* activeSelection is the variable that holds the active output of the switch
59 it is declared as an attribute that keeps its value between arduino resets
61 switchSelection_t activeSelection __attribute__ ((section (".noinit")));
63 // variables and timers for blinking selection (selected but not confirmed)
64 switchSelection_t blinkingSelection = nonstop;
65 bool blinkingLedState = RELAY_STATE_CLOSED;
66 unsigned long blinkingStartTime = 0, blinkingAbortTime = 0;
69 // declaration of possible button states as enum type
70 typedef enum { nochange, pressed, released } buttonEvent_t;
72 // button event timers
73 unsigned long button1LastEventTime = 0, button2LastEventTime = 0;
75 // variables holding the state of each button
76 // these are used during the debouncing process
77 uint8_t button1State = LOW, button2State = LOW;
79 // variables holding the non-stop status from studios 1 & 2
80 bool nonstop_via_stud1, nonstop_via_stud2;
83 buttonEvent_t debounce( const uint8_t buttonPin,
85 unsigned long *buttonLastEventTime );
87 static uint8_t mac[] = MAC_ADDRESS;
90 // instanciate web server
91 WebServer webserver(PREFIX, 80);
96 typedef enum responseStatus { NO_POST, POST_OK, POST_ERROR };
100 void webCmd(WebServer &server, WebServer::ConnectionType type, char *url_tail, bool tail_complete)
103 server.httpSuccess("application/json");
105 if (type == WebServer::HEAD)
108 responseStatus response_status = NO_POST;
110 if (type == WebServer::POST)
114 char value[VALUELEN];
117 response_status = POST_ERROR;
119 while (server.readPOSTparam(name, NAMELEN, value, VALUELEN))
121 if (strcmp(name, "s") == 0) {
122 digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED);
123 blinkingSelection = static_cast<switchSelection_t>(atoi(value));
124 activeSelection = static_cast<switchSelection_t>(atoi(value));
125 response_status = POST_OK;
130 server.println(F("{"));
132 server.print(" \"response\": ");
133 server.print(response_status);
135 server.print(",\n \"active\": ");
136 server.print(activeSelection);
138 server.print(",\n \"nonstop-via-stud1\": ");
139 server.print(nonstop_via_stud1);
140 server.print(",\n \"nonstop-via-stud2\": ");
141 server.println(nonstop_via_stud2);
143 server.println(F("}"));
150 // make sure that activeSelection holds something valid
151 // if (!(activeSelection > nonstop) || !(activeSelection < _NbrSwitchSelections))
152 // activeSelection = nonstop;
153 blinkingSelection = activeSelection = nonstop;
155 // open serial communication for debugging
157 Serial.println(F("Startup"));
159 // disable SD and Ethernet ports before setup
160 pinMode(SD_SELECT, OUTPUT);
161 digitalWrite(SD_SELECT, HIGH); // disable SD card
162 pinMode(ETHERNET_SELECT, OUTPUT);
163 digitalWrite(ETHERNET_SELECT, HIGH); // disable Ethernet
165 // start SPI (because Ethernet shield needs it)
166 SPI.begin(); // start SPI
169 if (!(Ethernet.begin(mac) == 0)) // start network
170 Serial.println(Ethernet.localIP());
173 Serial.println(F("Network Error"));
177 // set mode for used pins
178 pinMode(RELAY_RED_LEDS, OUTPUT);
179 digitalWrite(RELAY_RED_LEDS, RELAY_STATE_CLOSED);
180 pinMode(RELAY_YELLOW_LEDS, OUTPUT);
181 digitalWrite(RELAY_YELLOW_LEDS, RELAY_STATE_CLOSED);
182 pinMode(RELAY_GREEN_LEDS, OUTPUT);
183 digitalWrite(RELAY_GREEN_LEDS, RELAY_STATE_CLOSED);
184 pinMode(RELAY_BUTTON_LEDS, OUTPUT);
185 digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED);
187 pinMode(RELAY_NONSTOP_OR_STUD, OUTPUT);
188 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED);
189 pinMode(RELAY_STUD1_OR_STUD2, OUTPUT);
190 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
192 pinMode(BUTTON1, INPUT);
193 pinMode(BUTTON2, INPUT);
194 pinMode(NONSTOP_VIA_STUD1, INPUT);
195 pinMode(NONSTOP_VIA_STUD2, INPUT);
197 // configure web server pages
198 webserver.setDefaultCommand(&webCmd);
208 // update variables indicating if non-stop is selected in studios 1&2
209 nonstop_via_stud1 = digitalRead(NONSTOP_VIA_STUD1);
210 if (nonstop_via_stud1 == 0)
211 nonstop_via_stud1 = 1;
213 nonstop_via_stud1 = 0;
214 nonstop_via_stud2 = digitalRead(NONSTOP_VIA_STUD2);
215 if (nonstop_via_stud2 == 0)
216 nonstop_via_stud2 = 1;
218 nonstop_via_stud2 = 0;
220 // check if we have a HTTP request (and respond)
221 webserver.processConnection();
223 // handle button 1 (select button)
224 switch ( debounce(BUTTON1, &button1State, &button1LastEventTime) )
229 //Serial.println(F("Button 1 pressed"));
230 digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED);
232 blinkingStartTime = millis(),
233 blinkingAbortTime = millis();
234 blinkingLedState = RELAY_STATE_OPEN;
237 //Serial.println(F("Button 1 released"));
241 // handle button 2 (confirm button)
242 switch ( debounce(BUTTON2, &button2State, &button2LastEventTime) )
247 //Serial.println(F("Button 2 pressed"));
248 blinkingAbortTime = 0; // disable blinking auto abort
251 //Serial.println(F("Button 2 released"));
252 if (activeSelection != blinkingSelection)
254 digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED);
255 activeSelection = blinkingSelection; // relay states must be changed now
256 Serial.print(F("Active Selection: "));
257 Serial.println(activeSelection);
262 // handle auto abort for blinking led (if any)
263 if ( (blinkingAbortTime != 0) &&
264 ((millis() - blinkingAbortTime) >= ABORT_TRESHOLD) ) {
265 digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED);
266 blinkingAbortTime = 0;
267 blinkingSelection = activeSelection;
270 // handle blinking led (if selected is not current state)
271 if (activeSelection != blinkingSelection) {
272 if ((millis() - blinkingStartTime) >= BLINK_TRESHOLD) {
273 digitalWrite(ledsArray[blinkingSelection], blinkingLedState);
274 digitalWrite(RELAY_BUTTON_LEDS, !blinkingLedState);
275 blinkingStartTime = millis();
276 blinkingLedState = !blinkingLedState;
280 digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED);
283 digitalWrite(ledsArray[activeSelection], RELAY_STATE_OPEN);
285 // update audio channel relays
286 if (activeSelection == nonstop)
288 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED);
289 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
291 else if (activeSelection == studio1)
293 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN);
294 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
296 else if (activeSelection == studio2)
298 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN);
299 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_OPEN);
303 buttonEvent_t debounce( const uint8_t buttonPin,
304 uint8_t *buttonState,
305 unsigned long *buttonLastEventTime )
307 uint8_t buttonLastState = *buttonState;
308 uint8_t buttonReading = digitalRead(buttonPin);
310 if ( (*buttonLastEventTime == 0) &&
311 (*buttonState != buttonReading) ) {
312 // something happened, start the debouncing process
313 *buttonLastEventTime = millis();
316 if (*buttonLastEventTime != 0) {
317 long buttonEventTimer = millis() - *buttonLastEventTime;
319 if ( (buttonEventTimer < DEBOUNCE_TRESHOLD) &&
320 (*buttonState == buttonReading) ) {
321 // noise or bouncing, abort
322 *buttonLastEventTime = 0;
325 if ( (buttonEventTimer >= DEBOUNCE_TRESHOLD) &&
326 (buttonReading != *buttonState) ) {
327 // new button state was maintained
328 *buttonLastEventTime = 0;
329 *buttonState = buttonReading;
333 // debouncing finished, return button state
334 if (*buttonLastEventTime == 0) {
335 // comparing buttonState and buttonLastState tells whether the
336 // button is pressed or released
337 if ( (*buttonState == HIGH) &&
338 (buttonLastState == LOW) ) {
339 // button just pressed
340 buttonLastState = *buttonState;
343 if ( (*buttonState == LOW) &&
344 (buttonLastState == HIGH) ) {
345 // button just released
346 buttonLastState = *buttonState;