Guest User

Flipdot code

a guest
Aug 18th, 2017
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 14.29 KB | None | 0 0
  1. Flip-Disc controller code:
  2.  
  3. #include <Wire.h>
  4. #include <wwFlipdot02.h>
  5. #include <DS3231.h>
  6.  
  7. DS3231 clock;
  8. RTCDateTime dt;
  9.  
  10. // states of the process variable
  11. enum processStates {
  12.   STATE_WAITING, // i2c waiting for input
  13.   STATE_READ_HEADER, // first part of data read
  14.   STATE_READ_DATA, // parameters read (ex. image bits)
  15.   STATE_PROCESSED // data processed, waiting for alarm to reset display
  16. };
  17.  
  18. // types of data to display
  19. const char TYPE_IMAGE = 'i';
  20. const char TYPE_TEXT = 't'; // currently not used
  21. const char TYPE_CHANGE_TIME = 'c';
  22. const char TYPE_RESET = 'r';
  23. const char TYPE_DEBUG = 'd';
  24.  
  25. // characters for flip-disc display
  26.  
  27. boolean numbers[10][5][3] = {
  28.   {{1, 1, 1}, {1, 0, 1}, {1, 0, 1}, {1, 0, 1}, {1, 1, 1}}, //0
  29.   {{0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}}, //1
  30.   {{1, 1, 1}, {0, 0, 1}, {1, 1, 1}, {1, 0, 0}, {1, 1, 1}}, //2
  31.   {{1, 1, 1}, {0, 0, 1}, {1, 1, 1}, {0, 0, 1}, {1, 1, 1}}, //3
  32.   {{1, 0, 1}, {1, 0, 1}, {1, 1, 1}, {0, 0, 1}, {0, 0, 1}}, //4
  33.   {{1, 1, 1}, {1, 0, 0}, {1, 1, 1}, {0, 0, 1}, {1, 1, 1}}, //5
  34.   {{1, 1, 1}, {1, 0, 0}, {1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, //6
  35.   {{1, 1, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}, {0, 0, 1}}, //7
  36.   {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}, {1, 0, 1}, {1, 1, 1}}, //8
  37.   {{1, 1, 1}, {1, 0, 1}, {1, 1, 1}, {0, 0, 1}, {1, 1, 1}}, //9
  38.   };
  39.  
  40. boolean colon[5][3] = {
  41.   {0, 0, 0},
  42.   {0, 1, 0},
  43.   {0, 0, 0},
  44.   {0, 1, 0},
  45.   {0, 0, 0}
  46.   };
  47.  
  48. boolean dot[5][3] = {
  49.   {0, 0, 0},
  50.   {0, 0, 0},
  51.   {0, 0, 0},
  52.   {0, 0, 0},
  53.   {0, 1, 0}
  54.   };
  55.  
  56. // character positions for clock
  57.  
  58. byte positions[][2] = {
  59.   {2, 2},
  60.   {6, 2},
  61.   {9, 2},
  62.   {12, 2},
  63.   {16, 2},
  64.   {2, 9},
  65.   {6, 9},
  66.   {9, 9},
  67.   {12, 9},
  68.   {16, 9}
  69.   };
  70.  
  71. byte positions1[][2] = {
  72.   {7, 9},
  73.   {11, 9}
  74.   };
  75.  
  76. byte oldDay;
  77.  
  78. boolean configChange = false;
  79.  
  80. // variables affected by i2c data
  81. volatile char command = '\0';
  82. volatile char text[65] = "";
  83. volatile byte process = STATE_WAITING;
  84. volatile long len = 0;
  85. volatile long unix = 0;
  86. volatile short count = -1;
  87.  
  88. void setup() {
  89.   Serial.begin(9600);
  90.  
  91.   clock.begin();
  92.  
  93.   dt = clock.getDateTime();
  94.  
  95.   oldDay = dt.day;
  96.  
  97.   clock.armAlarm1(false);
  98.   clock.armAlarm2(false);
  99.   clock.clearAlarm1();
  100.   clock.clearAlarm2();
  101.  
  102.   //clock.setAlarm1(0, 0, 0, 0, DS3231_EVERY_SECOND, true);
  103.   clock.setAlarm2(0, 0, 0, DS3231_EVERY_MINUTE, true); // updates the clock
  104.  
  105.   // flip-disc setup (it starts at {1, 1}, not {0, 0}!)
  106.  
  107.   dotSetup(8, 21, 1, 16, 0);
  108.  
  109.   dotPowerOn();
  110.   delay(50);
  111.   resetAll(0);
  112.   delay(100);
  113.  
  114.   // i2c setup
  115.  
  116.   Wire.begin(105);
  117.   Wire.onReceive(receiveEvent);
  118.  
  119.   Serial.println("Setup done.");
  120.  
  121.   configChange = true; // refresh clock when entering main loop
  122. }
  123.  
  124. void loop() {
  125.   if(clock.isAlarm1() && process == STATE_PROCESSED) { // reset display and variables when time (len) has elapsed
  126.     clock.armAlarm1(false);
  127.     clock.clearAlarm1();
  128.     process = 0;
  129.     command = '\0';
  130.     len = 0;
  131.     unix = 0;
  132.     for(byte i = 0; i < 65; i++) {
  133.       text[i] = '\0';
  134.     }
  135.     count = -1;
  136.     Serial.println("Resetting flipdot (alarm triggered)...");
  137.     resetAll(0);
  138.     delay(50);
  139.     configChange = true; // update display (show clock or other data)
  140.   }
  141.   else if(process == STATE_PROCESSED || process == STATE_READ_HEADER) { // stop loop execution if something is (going to be) displayed
  142.     return;
  143.   }
  144.   else if(process == STATE_READ_DATA) { // process received data
  145.     Serial.println("Processing data...");
  146.     if(command == TYPE_IMAGE) {
  147.       Serial.println("Displaying image...");
  148.       for(byte i = 0; i < 42; i++) { // reconstruct image from 42 bytes and show it
  149.         byte x = floor((float) i / (float) 2) + 1;
  150.         byte y = 9;
  151.         if(i % 2 == 0) {
  152.           y = 1;
  153.         }
  154.         for(byte j = 0; j < 8; j++) {
  155.           if(((text[i] >> j) & 1) == 1) {
  156.             setDot(x, y + j);
  157.           }
  158.           else {
  159.             resetDot(x, y + j);
  160.           }
  161.           delay(1);
  162.         }
  163.       }
  164.       Serial.println("Displayed image!");
  165.     }
  166.     else if(command == TYPE_CHANGE_TIME) { // change clock time
  167.       unix += len; // add given offset to given time
  168.       Serial.print("Set time to ");
  169.       Serial.print(unix);
  170.       Serial.println(".");
  171.       clock.setDateTime(unix);
  172.     }
  173.     else if(command == 'r') { // reset display (done when alarm fires, configChange = true);
  174.       Serial.println("Reset flipdot!");
  175.     }
  176.     else if(command == 'd') { // debug display (if some of the dots aren´t working properly anymore)
  177.       Serial.println("Debugging flipdot...");
  178.       debug();
  179.       Serial.println("Debugged flipdot!");
  180.     }
  181.     delay(20);
  182.  
  183.     // set alarm for display reset
  184.    
  185.     dt = clock.getDateTime();
  186.     byte minu = dt.minute;
  187.     byte sec = dt.second + len;
  188.     byte hou = dt.hour;
  189.     if(command == TYPE_RESET || command == TYPE_CHANGE_TIME || command == TYPE_DEBUG) { // no changeable length for these types
  190.       sec = dt.second + 2;
  191.     }
  192.     while(sec > 59) {
  193.       minu++;
  194.       sec -= 60;
  195.     }
  196.     while(minu > 59) {
  197.       hou++;
  198.       minu -= 60;
  199.     }
  200.     oldDay = dt.day; // prevent midnight debug if day was changed (see clock displaying)
  201.     clock.setAlarm1(dt.day, hou, minu, sec, DS3231_MATCH_DT_H_M_S);
  202.     process = STATE_PROCESSED;
  203.     return;
  204.   }
  205.  
  206.   // show clock if nothing else is currently being displayed
  207.   if((clock.isAlarm2() || configChange) && (process != 1 && process != 2 && process != 3)) {
  208.     // convert time into displayable text and add zeros
  209.    
  210.     dt = clock.getDateTime();
  211.     char hour[3] = "";
  212.     itoa(dt.hour, hour, 10);
  213.     char minute[3] = "";
  214.     itoa(dt.minute, minute, 10);
  215.     char month[3] = "";
  216.     itoa(dt.month, month, 10);
  217.     char day[3] = "";
  218.     itoa(dt.day, day, 10);
  219.  
  220.     if(dt.day != oldDay) { // run debug at midnight
  221.       debug();
  222.       oldDay = dt.day;
  223.     }
  224.    
  225.     if(strlen(hour) == 1) {
  226.       char num = hour[0];
  227.       hour[0] = '0';
  228.       hour[1] = num;
  229.     }
  230.    
  231.     if(strlen(minute) == 1) {
  232.       char num = minute[0];
  233.       minute[0] = '0';
  234.       minute[1] = num;
  235.     }
  236.    
  237.     if(strlen(month) == 1) {
  238.       char num = month[0];
  239.       month[0] = '0';
  240.       month[1] = num;
  241.     }
  242.    
  243.     if(strlen(day) == 1) {
  244.       char num = day[0];
  245.       day[0] = '0';
  246.       day[1] = num;
  247.     }
  248.  
  249.     // array containing data to display (conversion of chars to number from array)
  250.     boolean (*data[])[3] = {
  251.       numbers[((byte) hour[0]) - 48],
  252.       numbers[((byte) hour[1]) - 48],
  253.       colon,
  254.       numbers[((byte) minute[0]) - 48],
  255.       numbers[((byte) minute[1]) - 48],
  256.       numbers[((byte) day[0]) - 48],
  257.       numbers[((byte) day[1]) - 48],
  258.       dot,
  259.       numbers[((byte) month[0]) - 48],
  260.       numbers[((byte) month[1]) - 48]
  261.       };
  262.      
  263.     // display the numbers at given positions from position array
  264.     for(byte i = 0; i < 10; i++) {
  265.       for(byte j = 0; j < 5; j++) {
  266.         for(byte k = 0; k < 3; k++) {
  267.           if(data[i][j][k]) {
  268.             setDot(positions[i][0] + k + 1, positions[i][1] + j + 1);
  269.           }
  270.           else {
  271.             resetDot(positions[i][0] + k + 1, positions[i][1] + j + 1);
  272.           }
  273.           delay(5);
  274.         }
  275.       }
  276.     }
  277.     configChange = false; // reset update mode (don´t update another time)
  278.   }
  279. }
  280.  
  281. //i2c receive
  282. void receiveEvent(int howMany) {
  283.   if(process == STATE_READ_DATA || process == STATE_PROCESSED) { // only one block of data can be displayed at the same time, no queue
  284.     return;
  285.   }
  286.  
  287.   char arg[5] = ""; // simple arguments
  288.  
  289.   while(Wire.available() > 0) {
  290.     char c = Wire.read();
  291.     count++; // represents the position in array for arguments
  292.     if(process == STATE_WAITING) { // first step
  293.       if(count == 0) {
  294.         command = c;
  295.       }
  296.       else if(count > 0 && count < 5) { // set length/offset argument
  297.         arg[count - 1] = c;
  298.       }
  299.       else if(count > 4) {
  300.         // reconstruct long from 4 bytes (arg array)
  301.         len = 0b00000000000000000000000000000000;
  302.         byte multiplier = 0;
  303.         for(byte i = 0; i < 32; i++) {
  304.           if(i % 8 == 0 && i != 0) {
  305.             multiplier++;
  306.           }
  307.           if(((arg[multiplier] >> (i - multiplier * 8)) & 1) == 1) {
  308.             bitSet(len, i);
  309.           }
  310.         }
  311.         // update for next step
  312.         process = STATE_READ_HEADER;
  313.         count = -1;
  314.       }
  315.     }
  316.     else if(process == STATE_READ_HEADER) { // second step
  317.       if(command == TYPE_IMAGE) {
  318.         if(count == 42) {
  319.           // update for processing
  320.           count = -1;
  321.           process = STATE_READ_DATA;
  322.         }
  323.         else {
  324.           if(count < 42 && count > -1) {
  325.             text[count] = c; // write bytes to text array
  326.           }
  327.         }
  328.       }
  329.       else if(command == TYPE_CHANGE_TIME) {
  330.         if(c == '\0') {
  331.           // reconstruct time (long) from 4 bytes (arg array)
  332.           unix = 0b00000000000000000000000000000000;
  333.           byte multiplier = 0;
  334.           for(byte i = 0; i < 32; i++) {
  335.             if(i % 8 == 0 && i != 0) {
  336.               multiplier++;
  337.             }
  338.             if(((arg[multiplier] >> (i - multiplier * 8)) & 1) == 1) {
  339.               bitSet(unix, i);
  340.             }
  341.           }
  342.           // update for processing
  343.           count = -1;
  344.           process = STATE_READ_DATA;
  345.         }
  346.         else {
  347.           if(count < 4 && count > -1) {
  348.             arg[count] = c; // write new time to arg array
  349.           }
  350.         }
  351.       }
  352.       else if(command == TYPE_RESET || command == TYPE_DEBUG) {
  353.         // update for processing
  354.         count = -1;
  355.         process = STATE_READ_DATA;
  356.       }
  357.     }
  358.   }
  359. }
  360.  
  361. // debug display
  362. void debug() {
  363.   for(byte i = 18; i >= 3; i -= 3) {
  364.     setAll(i - 3);
  365.     delay(100);
  366.     resetAll(i - 3);
  367.     delay(100);
  368.   }
  369. }
  370.  
  371.  
  372. Ethernet arduino code:
  373.  
  374. #include <SPI.h>
  375. #include <Ethernet.h>
  376. #include <Wire.h>
  377.  
  378. #define RESET 2
  379.  
  380. byte mac[] = {
  381.   0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
  382. };
  383.  
  384. EthernetServer server(80);
  385.  
  386. void setup() {
  387.   // init reset pin (resets display when low)
  388.   pinMode(RESET, OUTPUT);
  389.   digitalWrite(RESET, HIGH);
  390.  
  391.   Serial.begin(9600);
  392.   Wire.begin();
  393.  
  394.   Ethernet.begin(mac);
  395.   server.begin();
  396.  
  397.   Serial.print("Flipdot Server is at ");
  398.   Serial.println(Ethernet.localIP());
  399. }
  400.  
  401.  
  402. void loop() {
  403.   EthernetClient client = server.available();
  404.   if (client) {
  405.     Serial.println();
  406.     char arg[350] = "";
  407.     boolean currentLineIsBlank = true;
  408.     byte commandPos = 0;
  409.     while (client.connected()) {
  410.       if (client.available()) {
  411.         char c = client.read();
  412.         // write data to array
  413.         if(c == '/' && commandPos == 0) {
  414.           commandPos = 1;
  415.         }
  416.         else if(c == ' ' && commandPos == 1) {
  417.           commandPos = 2;
  418.         }
  419.         else if(commandPos == 1) {
  420.           char str[2] = {c, '\0'};
  421.           strcat(arg, str);
  422.         }
  423.        
  424.         if (c == '\n' && currentLineIsBlank) {
  425.           client.println("HTTP/1.1 200 OK");
  426.           client.println("Content-Type: text/html");
  427.           client.println("Access-Control-Allow-Origin: *");
  428.           client.println("Connection: close");
  429.           client.println();
  430.           client.println("<!DOCTYPE HTML>");
  431.           client.println("<html>");
  432.           client.println("Request answered");
  433.           client.println("</html>");
  434.           break;
  435.         }
  436.         if (c == '\n') {
  437.           currentLineIsBlank = true;
  438.         } else if (c != '\r') {
  439.           currentLineIsBlank = false;
  440.         }
  441.       }
  442.     }
  443.     delay(1);
  444.     client.stop();
  445.  
  446.     if(arg[0] == 'x') { // hard-reset display
  447.       digitalWrite(RESET, LOW);
  448.       delay(10);
  449.       digitalWrite(RESET, HIGH);
  450.       return;
  451.     }
  452.  
  453.     Serial.println("Sending received data to flipdot...");
  454.    
  455.     Wire.beginTransmission(105);
  456.    
  457.     Wire.write(arg[0]); // write command
  458.     // convert length string to 4 bytes of data
  459.     char len[11] = "";
  460.     for(byte i = 2; i < 12; i++) {
  461.       len[i - 2] = arg[i];
  462.     }
  463.     len[10] = '\0';
  464.     long lenL = atol(len);
  465.     {
  466.       byte multiplier = 0;
  467.       byte buf = 0b00000000;
  468.       for(byte i = 0; i < 32; i++) {
  469.         if(i % 8 == 0 && i != 0) {
  470.           multiplier++;
  471.           Wire.write(buf);
  472.           buf = 0b00000000;
  473.         }
  474.         if(((lenL >> i) & 1) == 1) {
  475.           buf |= 1 << (i - multiplier * 8);
  476.         }
  477.       }
  478.       Wire.write(buf);
  479.       Wire.write('\0');
  480.     }
  481.     Serial.println("Sending header data...");
  482.    
  483.     byte state = Wire.endTransmission();
  484.    
  485.     Wire.beginTransmission(105);
  486.  
  487.     if(arg[0] == 'i') { // if data is image
  488.       // convert 336 char string to 42 bytes of data
  489.       byte multiplier = 0;
  490.       byte buf = 0b00000000;
  491.       for(int i = 0; i < strlen(arg) - 12; i++) {
  492.         if(i % 8 == 0 && i != 0) {
  493.           multiplier++;
  494.           Wire.write(buf);
  495.           buf = 0b00000000;
  496.           if(multiplier % 32 == 0 && multiplier != 0) {
  497.             byte s = Wire.endTransmission();
  498.             if(s != 0) {
  499.               state = 1;
  500.             }
  501.             Wire.beginTransmission(105);
  502.           }
  503.           if(multiplier == 42) {
  504.             break;
  505.           }
  506.         }
  507.         if(arg[i + 13] == '1') {
  508.           buf |= 1 << (i - multiplier * 8);
  509.         }
  510.       }
  511.       Wire.write('\0');
  512.       Serial.println("Sending 42 bytes of image data...");
  513.     }
  514.     else if(arg[0] == 'c') { // if type is change time
  515.       // convert time string to 4 bytes of data
  516.       char unix[11] = "";
  517.       for(byte i = 13; i < 23; i++) {
  518.         unix[i - 13] = arg[i];
  519.       }
  520.       unix[10] = '\0';
  521.       long unixL = atol(unix);
  522.       byte multiplier = 0;
  523.       byte buf = 0b00000000;
  524.       for(byte i = 0; i < 32; i++) {
  525.         if(i % 8 == 0 && i != 0) {
  526.           multiplier++;
  527.           Wire.write(buf);
  528.           buf = 0b00000000;
  529.         }
  530.         if(((unixL >> i) & 1) == 1) {
  531.           buf |= 1 << (i - multiplier * 8);
  532.         }
  533.       }
  534.       Wire.write(buf);
  535.       Wire.write('\0');
  536.     }
  537.     else if(arg[0] == 'r' || arg[0] == 'd') { // if type is reset or debug
  538.       Wire.write('\0');
  539.     }
  540.  
  541.     // send data and check for errors
  542.     if(Wire.endTransmission() == 0 && state == 0) {
  543.       Serial.println("All data successfully sent!");
  544.     }
  545.     else {
  546.       Serial.println("An error occurred while sending the data!");
  547.     }
  548.   }
  549. }
Add Comment
Please, Sign In to add comment