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)
115 char value[VALUELEN];
118 response_status = POST_ERROR;
120 while (server.readPOSTparam(name, NAMELEN, value, VALUELEN))
122 if (strcmp(name, "s") == 0) {
123 digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED);
124 blinkingSelection = static_cast<switchSelection_t>(atoi(value));
125 activeSelection = static_cast<switchSelection_t>(atoi(value));
126 response_status = POST_OK;
131 server.println(F("{"));
133 server.print(" \"response\": ");
134 server.print(response_status);
136 server.print(",\n \"active\": ");
137 server.print(activeSelection);
139 server.print(",\n \"nonstop-via-stud1\": ");
140 server.print(nonstop_via_stud1);
141 server.print(",\n \"nonstop-via-stud2\": ");
142 server.println(nonstop_via_stud2);
144 server.println(F("}"));
151 // make sure that activeSelection holds something valid
152 // if (!(activeSelection > nonstop) || !(activeSelection < _NbrSwitchSelections))
153 // activeSelection = nonstop;
154 blinkingSelection = activeSelection = nonstop;
156 // open serial communication for debugging
158 Serial.println(F("Startup"));
160 // disable SD and Ethernet ports before setup
161 pinMode(SD_SELECT, OUTPUT);
162 digitalWrite(SD_SELECT, HIGH); // disable SD card
163 pinMode(ETHERNET_SELECT, OUTPUT);
164 digitalWrite(ETHERNET_SELECT, HIGH); // disable Ethernet
166 // start SPI (because Ethernet shield needs it)
167 SPI.begin(); // start SPI
170 if (!(Ethernet.begin(mac) == 0)) // start network
171 Serial.println(Ethernet.localIP());
174 Serial.println(F("Network Error"));
178 // set mode for used pins
179 pinMode(RELAY_RED_LEDS, OUTPUT);
180 digitalWrite(RELAY_RED_LEDS, RELAY_STATE_CLOSED);
181 pinMode(RELAY_YELLOW_LEDS, OUTPUT);
182 digitalWrite(RELAY_YELLOW_LEDS, RELAY_STATE_CLOSED);
183 pinMode(RELAY_GREEN_LEDS, OUTPUT);
184 digitalWrite(RELAY_GREEN_LEDS, RELAY_STATE_CLOSED);
185 pinMode(RELAY_BUTTON_LEDS, OUTPUT);
186 digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED);
188 pinMode(RELAY_NONSTOP_OR_STUD, OUTPUT);
189 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED);
190 pinMode(RELAY_STUD1_OR_STUD2, OUTPUT);
191 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
193 pinMode(BUTTON1, INPUT);
194 pinMode(BUTTON2, INPUT);
195 pinMode(NONSTOP_VIA_STUD1, INPUT);
196 pinMode(NONSTOP_VIA_STUD2, INPUT);
198 // configure web server pages
199 webserver.setDefaultCommand(&webCmd);
209 // update variables indicating if non-stop is selected in studios 1&2
210 nonstop_via_stud1 = digitalRead(NONSTOP_VIA_STUD1);
211 if (nonstop_via_stud1 == 0)
212 nonstop_via_stud1 = 1;
214 nonstop_via_stud1 = 0;
215 nonstop_via_stud2 = digitalRead(NONSTOP_VIA_STUD2);
216 if (nonstop_via_stud2 == 0)
217 nonstop_via_stud2 = 1;
219 nonstop_via_stud2 = 0;
221 // check if we have a HTTP request (and respond)
222 webserver.processConnection();
224 // handle button 1 (select button)
225 switch ( debounce(BUTTON1, &button1State, &button1LastEventTime) )
230 //Serial.println(F("Button 1 pressed"));
231 digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED);
233 blinkingStartTime = millis(),
234 blinkingAbortTime = millis();
235 blinkingLedState = RELAY_STATE_OPEN;
238 //Serial.println(F("Button 1 released"));
242 // handle button 2 (confirm button)
243 switch ( debounce(BUTTON2, &button2State, &button2LastEventTime) )
248 //Serial.println(F("Button 2 pressed"));
249 blinkingAbortTime = 0; // disable blinking auto abort
252 //Serial.println(F("Button 2 released"));
253 if (activeSelection != blinkingSelection)
255 digitalWrite(ledsArray[activeSelection], RELAY_STATE_CLOSED);
256 activeSelection = blinkingSelection; // relay states must be changed now
257 Serial.print(F("Active Selection: "));
258 Serial.println(activeSelection);
263 // handle auto abort for blinking led (if any)
264 if ( (blinkingAbortTime != 0) &&
265 ((millis() - blinkingAbortTime) >= ABORT_TRESHOLD) ) {
266 digitalWrite(ledsArray[blinkingSelection], RELAY_STATE_CLOSED);
267 blinkingAbortTime = 0;
268 blinkingSelection = activeSelection;
271 // handle blinking led (if selected is not current state)
272 if (activeSelection != blinkingSelection) {
273 if ((millis() - blinkingStartTime) >= BLINK_TRESHOLD) {
274 digitalWrite(ledsArray[blinkingSelection], blinkingLedState);
275 digitalWrite(RELAY_BUTTON_LEDS, !blinkingLedState);
276 blinkingStartTime = millis();
277 blinkingLedState = !blinkingLedState;
281 digitalWrite(RELAY_BUTTON_LEDS, RELAY_STATE_CLOSED);
284 digitalWrite(ledsArray[activeSelection], RELAY_STATE_OPEN);
286 // update audio channel relays
287 if (activeSelection == nonstop)
289 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_CLOSED);
290 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
292 else if (activeSelection == studio1)
294 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN);
295 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_CLOSED);
297 else if (activeSelection == studio2)
299 digitalWrite(RELAY_NONSTOP_OR_STUD, RELAY_STATE_OPEN);
300 digitalWrite(RELAY_STUD1_OR_STUD2, RELAY_STATE_OPEN);
304 buttonEvent_t debounce( const uint8_t buttonPin,
305 uint8_t *buttonState,
306 unsigned long *buttonLastEventTime )
308 uint8_t buttonLastState = *buttonState;
309 uint8_t buttonReading = digitalRead(buttonPin);
311 if ( (*buttonLastEventTime == 0) &&
312 (*buttonState != buttonReading) ) {
313 // something happened, start the debouncing process
314 *buttonLastEventTime = millis();
317 if (*buttonLastEventTime != 0) {
318 long buttonEventTimer = millis() - *buttonLastEventTime;
320 if ( (buttonEventTimer < DEBOUNCE_TRESHOLD) &&
321 (*buttonState == buttonReading) ) {
322 // noise or bouncing, abort
323 *buttonLastEventTime = 0;
326 if ( (buttonEventTimer >= DEBOUNCE_TRESHOLD) &&
327 (buttonReading != *buttonState) ) {
328 // new button state was maintained
329 *buttonLastEventTime = 0;
330 *buttonState = buttonReading;
334 // debouncing finished, return button state
335 if (*buttonLastEventTime == 0) {
336 // comparing buttonState and buttonLastState tells whether the
337 // button is pressed or released
338 if ( (*buttonState == HIGH) &&
339 (buttonLastState == LOW) ) {
340 // button just pressed
341 buttonLastState = *buttonState;
344 if ( (*buttonState == LOW) &&
345 (buttonLastState == HIGH) ) {
346 // button just released
347 buttonLastState = *buttonState;