diff --git a/flipcontrol_esp32/include/flipdot.h b/flipcontrol_esp32/include/flipdot.h new file mode 100644 index 0000000..d6ca7d4 --- /dev/null +++ b/flipcontrol_esp32/include/flipdot.h @@ -0,0 +1,78 @@ +#ifndef FLIPDOT_H +#define FLIPDOT_H + +#include + +#define CHECK_BIT(var,pos) ((var) & (1<<(pos))) + +/* +D7 - Ser (data) +D5 - clock +D1 - _OE +D2 - latch +D3 - _clear +*/ + +//Pins connected to Shift registers on own controller board +#define PIN_DATA 13 +#define PIN_CLK 14 +#define PIN_OE 27 //active low +#define PIN_LATCH 26 + + +//Pins connected to stuff on annax driver board +#define PIN_DATA_DRVBRD 33 +#define PIN_CLK_DRVBRD 32 + +//#define PIN_CLEAR 25 //active low + +#define PIN_DRIVE 25 //enables 12v to panels via transistor +#define PIN_CLEAR 12 //connects CLEAR Pin from Annax board to GND (clears column) + +#define NUMPANELS 1 +#define COLUMNBYTES 7 //4 columns per byte. one panel has 25 columns + + +//### Timings ### +#define MICROS_DRIVEDOTSET 1500 //time dot will be powered for flipping to bright side. in microseconds. 700 sometimes flips too late +#define MICROS_DRIVEDOTCLEAR 20000 //time dot will be powered for flipping to black. in microseconds. always flips at least a whole column. 10000 is too short + +#define MICROS_SHIFTDELAY 50/2 //shift register clock (100/2 = 1/(100/1000000) Hz) .at 25/2 nothing is flipping! +#define MICROS_SHIFT_LATCH 100 //latch high time for 595 (row drivers) + +class Flipdot +{ + +private: + int blafoo; + + + + + +public: + Flipdot(); + void init(); + + + void shiftOutSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); + bool clearSelectedColumn(); + bool setSelectedDot(); + + void selectColumnClear(uint8_t selcolumn); + void selectColumnSet(uint8_t selcolumn); + void selectColumn(uint8_t selcolumn, bool clear); + + bool HBridgeOK(); + void shiftData(); + + void resetColumns(); + + + uint16_t row; //controls shift registers on own controller pcb + + uint8_t col[COLUMNBYTES]; //column drivers and shift registers on annax pcb +}; + +#endif + diff --git a/flipcontrol_esp32/src/flipdot.cpp b/flipcontrol_esp32/src/flipdot.cpp new file mode 100644 index 0000000..4d9b7ab --- /dev/null +++ b/flipcontrol_esp32/src/flipdot.cpp @@ -0,0 +1,148 @@ +#include "flipdot.h" + + + +Flipdot::Flipdot() +{ + +} + +void Flipdot::init() +{ + pinMode(PIN_DATA, OUTPUT); + pinMode(PIN_CLK, OUTPUT); + pinMode(PIN_OE, OUTPUT); + pinMode(PIN_LATCH, OUTPUT); + pinMode(PIN_CLEAR, OUTPUT); + pinMode(PIN_DRIVE, OUTPUT); + + + pinMode(PIN_DATA_DRVBRD, OUTPUT); + pinMode(PIN_CLK_DRVBRD, OUTPUT); + + + digitalWrite(PIN_OE, HIGH); //Active Low + digitalWrite(PIN_LATCH, LOW); + + digitalWrite(PIN_DRIVE, LOW); +} + + + +void Flipdot::shiftOutSlow(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) +{ + uint8_t i; + + for (i = 0; i < 8; i++) { + if (bitOrder == LSBFIRST) + digitalWrite(dataPin, !!(val & (1 << i))); + else + digitalWrite(dataPin, !!(val & (1 << (7 - i)))); + + delayMicroseconds(MICROS_SHIFTDELAY); + digitalWrite(clockPin, HIGH); + delayMicroseconds(MICROS_SHIFTDELAY); + digitalWrite(clockPin, LOW); + } +} + + +void Flipdot::selectColumnClear(uint8_t selcolumn) { + selectColumn(selcolumn, true); +} +void Flipdot::selectColumnSet(uint8_t selcolumn) { + selectColumn(selcolumn, false); +} +void Flipdot::selectColumn(uint8_t selcolumn, bool clear) { + uint8_t sc_bit=3-(selcolumn%4); //each two shift registers control four columns + uint8_t sc_byte=selcolumn/4; + + resetColumns(); + + col[sc_byte]=pow(2, (sc_bit*2+clear)); // possible numbers for clear=false: 1,4,16,64 +} + +bool Flipdot::clearSelectedColumn() { + //Clear Columns + if (row!=0) { + return 0; //error. row is selected (short circuit!) + } + for (uint8_t cc=0;cc<7;cc++) { + //Serial.print("checking cc="); Serial.println(cc); + for (uint8_t i=0;i<8;i+=2) { + if (CHECK_BIT(col[cc],i)) { + Serial.print("Error on bit "); + Serial.print(i); Serial.print(" col="); Serial.println(cc); + return 0; //a column is set to ground (should not be set for clear column) + } + } + } + + digitalWrite(PIN_DRIVE, HIGH); + digitalWrite(PIN_CLEAR, HIGH); + delayMicroseconds(MICROS_DRIVEDOTCLEAR); + digitalWrite(PIN_CLEAR, LOW); + digitalWrite(PIN_DRIVE, LOW); + return 1; +} + +bool Flipdot::setSelectedDot() { + + for (uint8_t cc=0;cc<7;cc++) { + //Serial.print("checking cc="); Serial.println(cc); + for (uint8_t i=1;i<8;i+=2) { + if (CHECK_BIT(col[cc],i)) { + Serial.print("Error on bit "); + Serial.print(i); Serial.print(" col="); Serial.println(cc); + return 0; //a column is set to ground (should not be set for clear column) + } + } + } + + if (!HBridgeOK()) { + return 0; + } + + digitalWrite(PIN_OE, LOW); //Active Low + digitalWrite(PIN_DRIVE, HIGH); + delayMicroseconds(MICROS_DRIVEDOTSET); //Drive Dot + digitalWrite(PIN_OE, HIGH); //Active Low + digitalWrite(PIN_DRIVE, LOW); + return 1; +} + +bool Flipdot::HBridgeOK() { + for (uint8_t cc=0;cc<7;cc++) { + //Serial.print("checking cc="); Serial.println(cc); + for (uint8_t i=0;i<8;i+=2) { + if (CHECK_BIT(col[cc],i) && CHECK_BIT(col[cc],i+1)) { + Serial.print("Short circuit on bit "); + Serial.print(i); Serial.print(" col="); Serial.println(cc); + return 0; //a column is set to ground (should not be set for clear column) + } + } + } + return 1; +} + +void Flipdot::shiftData() { //send out all data to shift registers + + + //select Rows via shift registers on own controller board + shiftOutSlow(PIN_DATA, PIN_CLK, LSBFIRST, row&0xff); //lower byte + shiftOutSlow(PIN_DATA, PIN_CLK, LSBFIRST, row>>8); //LSBFIRST= LSB is QH, bit 8 is QA. //upper byte + digitalWrite(PIN_LATCH, HIGH); + delayMicroseconds(MICROS_SHIFT_LATCH); + digitalWrite(PIN_LATCH, LOW); + + //Select Columns via Shift registers + for (uint8_t i=0;i<7;i++) { + shiftOutSlow(PIN_DATA_DRVBRD, PIN_CLK_DRVBRD, LSBFIRST, col[6-i]); + } +} + +void Flipdot::resetColumns() { + for (uint8_t i=0;i<7;i++) { + col[i]=0; + } +} \ No newline at end of file diff --git a/flipcontrol_esp32/src/main.cpp b/flipcontrol_esp32/src/main.cpp index e4fe32a..d90ddba 100644 --- a/flipcontrol_esp32/src/main.cpp +++ b/flipcontrol_esp32/src/main.cpp @@ -10,7 +10,7 @@ Flipdot flipdot; unsigned long loopmillis=0; unsigned long last_update=0; -#define UPDATE_INTERVAL 10 +#define UPDATE_INTERVAL 5 void setup() { flipdot.init(); @@ -20,15 +20,23 @@ void setup() { int countz=0; +void loop_testDots(); +void loop_drawClearTest(); void loop() { loopmillis = millis(); + //loop_drawClearTest(); + loop_testDots(); + +} + +void loop_testDots() { + static bool init=false; if (!init) { - delay(2000); flipdot.row=0; Serial.println("Clearing Display"); for (int l=0;l<25;l++) { @@ -42,7 +50,73 @@ void loop() { Serial.println("Cleared"); } - delay(10); + delay(50); + } + init=true; + Serial.println("Finished Clearing"); + delay(1000); + } + + + + + Serial.println("Clearing"); + flipdot.row=0; + flipdot.selectColumnClear(23); + flipdot.shiftData(); + if (!flipdot.clearSelectedColumn()) { + Serial.println("Error clearing column!"); + } + delay(50); + + flipdot.row=0; + flipdot.selectColumnClear(24); + flipdot.shiftData(); + if (!flipdot.clearSelectedColumn()) { + Serial.println("Error clearing column!"); + } + delay(100); + + + Serial.println("Setting"); + for (int i=23;i<25;i++) { + flipdot.selectColumnSet(i); //lower column number is on the left + + flipdot.row=0; + flipdot.row+=pow(2, 4);//low significant bits are lower rows (when connector at top) + flipdot.row+=pow(2, 5);//low significant bits are lower rows (when connector at top) + flipdot.shiftData(); + flipdot.setSelectedDot(); + delay(50); + } + + delay(100); + + countz++; + countz%=14; + + //init=false; +} + + +void loop_drawClearTest() { + + static bool init=false; + if (!init) { + flipdot.row=0; + Serial.println("Clearing Display"); + for (int l=0;l<25;l++) { + flipdot.selectColumnClear(l%25); + + flipdot.shiftData(); + + if (!flipdot.clearSelectedColumn()) { + Serial.println("Error clearing column!"); + }else{ + Serial.println("Cleared"); + } + + delay(20); } init=true; delay(1000);