Last active
May 2, 2024 22:50
-
-
Save powerswitch/79e91f8f2d5f311f0734438726b63486 to your computer and use it in GitHub Desktop.
Arduino code for ET6202 LED driver chip
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Connect your ET6202 pins and adapt constants below accordingly | |
const int kPinStb = 4; // Serial interface command mode port | |
const int kPinClk = 3; // Clock input port | |
const int kPinData = 2; // Data input and output port | |
/** | |
* Command (aka Order) to send to the chip. | |
*/ | |
enum Order { | |
eOrderSetDisplayMode = B00000000, // Display mode command set [B00....aa], aa = DisplayMode | |
eOrderSetData = B01000000, // Set the order data [B01..abc.], a = TestMode, b = AutoIncrementAddress, c = ReadKey | |
eOrderSetAddress = B11000000, // Address set up a command [B11..aaaa], aaaa = Address | |
eOrderSetDisplayControl = B10000000, // Display control order [B10..abbb], a = EnableDisplay, bbb = DimmingLevel | |
}; | |
/** | |
* Display mode to set via Order 1 command. | |
*/ | |
enum DisplayMode { | |
eDisplayMode13char4bit = B00000000, // 13 paragraph x 4 bits | |
eDisplayMode12char5bit = B00000001, // 12 paragraph x 5 bits | |
eDisplayMode11char6bit = B00000010, // 11 paragraph x 6 bits | |
eDisplayMode10char7bit = B00000011, // 10 paragraph x 7 bits | |
}; | |
const byte imageLen = 14; | |
byte image[imageLen]; // stores the current state of the display | |
/** | |
* Send a byte via SPI interface. | |
* | |
* @param data: byte to send. | |
*/ | |
void send_data(byte data) | |
{ | |
shiftOut(kPinData, kPinClk, LSBFIRST, data); | |
} | |
/** | |
* Set display mode (Order 1). | |
* | |
* @param mode: DisplayMode to set | |
*/ | |
void set_display_mode(DisplayMode mode) | |
{ | |
digitalWrite(kPinStb, LOW); | |
send_data(eOrderSetDisplayMode | mode); | |
digitalWrite(kPinStb, HIGH); | |
} | |
/** | |
* Set data flags (Order 2). | |
* | |
* @param testmode: enable test mode | |
* @param autoincrement: enable auto address increment | |
* @param readmode: enable reading the key scan data | |
*/ | |
void set_data_flags(bool testmode, bool autoincrement, bool readmode) | |
{ | |
digitalWrite(kPinStb, LOW); | |
send_data(eOrderSetData | (B00001000 * testmode) | (B00000100 * autoincrement) | (B00000010 * readmode)); | |
digitalWrite(kPinStb, HIGH); | |
} | |
/** | |
* Set address (Order 3). | |
* | |
* @param address: address to set (0x00 .. 0x0D, default 0x00). | |
* | |
* @hint: address will change automatically when autoincrement was set in set_data_order command. | |
*/ | |
void set_address(byte address) | |
{ | |
digitalWrite(kPinStb, LOW); | |
send_data(eOrderSetAddress | (B00001111 & address)); | |
digitalWrite(kPinStb, HIGH); | |
} | |
/** | |
* Send byte at address. | |
* | |
* @param address: address to set (0x00 .. 0x0D, default 0x00). | |
* @param data: byte to send. | |
*/ | |
void send_at_address(byte address, byte data) | |
{ | |
digitalWrite(kPinStb, LOW); | |
send_data(eOrderSetAddress | (B00001111 & address)); | |
send_data(data); | |
digitalWrite(kPinStb, HIGH); | |
} | |
/** | |
* Send byte array at address. | |
* | |
* @param address: address to set (0x00 .. 0x0D, default 0x00). | |
* @param data: array of bytes to send. | |
* @param len: length of array. | |
*/ | |
void send_array_at_address(byte address, byte *data, byte len) | |
{ | |
digitalWrite(kPinStb, LOW); | |
send_data(eOrderSetAddress | (B00001111 & address)); | |
for (byte i = 0; i < len; i++) | |
{ | |
send_data(data[i]); | |
} | |
digitalWrite(kPinStb, HIGH); | |
} | |
/** | |
* Set display control flags (Order 4). | |
* | |
* @param enable: enable display | |
* @param brightness: set dimmer brightness (0x00 .. 0x07) | |
*/ | |
void set_display_control(bool enable, byte brightness) | |
{ | |
digitalWrite(kPinStb, LOW); | |
send_data(eOrderSetDisplayControl | (B00001000 * enable) | (B00001111 & brightness)); | |
digitalWrite(kPinStb, HIGH); | |
} | |
/** | |
* Refresh display of image array. | |
*/ | |
void refresh_display() | |
{ | |
set_display_mode(eDisplayMode10char7bit); | |
set_data_flags(false, false, false); | |
send_array_at_address(0, image, imageLen); | |
set_display_control(true, 7); | |
} | |
/** | |
* Poll key/button memory from chip. | |
*/ | |
byte poll_keys() | |
{ | |
set_display_control(false, 7); | |
digitalWrite(kPinStb, LOW); | |
send_data(eOrderSetData | B00000010); | |
pinMode(kPinData, INPUT); | |
const byte keys = shiftIn(kPinData, kPinClk, LSBFIRST); | |
digitalWrite(kPinStb, HIGH); | |
pinMode(kPinData, OUTPUT); | |
set_display_control(true, 7); | |
return keys; | |
} | |
// the following functions depend on the display configuration and might not match all types | |
/** | |
* Select segments of a seven segment digit. | |
* | |
* @param pos: position of digit | |
* @param a: segment a | |
* @param b: segment b | |
* @param c: segment c | |
* @param d: segment d | |
* @param e: segment e | |
* @param f: segment f | |
* @param g: segment g | |
*/ | |
void show_digit(byte pos, bool a, bool b, bool c, bool d, bool e, bool f, bool g) | |
{ | |
byte add = 0; | |
byte shift = 0; | |
switch (pos) | |
{ | |
case 0: | |
shift = 1; | |
break; | |
case 1: | |
shift = 0; | |
break; | |
case 2: | |
shift = 2; | |
break; | |
case 3: | |
shift = 7; | |
break; | |
case 4: | |
shift = 0; | |
add = 1; | |
break; | |
} | |
if (a) image[12+add] |= 1 << shift; else image[12+add] &= ~(1 << shift); | |
if (b) image[2+add] |= 1 << shift; else image[2+add] &= ~(1 << shift); | |
if (c) image[4+add] |= 1 << shift; else image[4+add] &= ~(1 << shift); | |
if (d) image[6+add] |= 1 << shift; else image[6+add] &= ~(1 << shift); | |
if (e) image[8+add] |= 1 << shift; else image[8+add] &= ~(1 << shift); | |
if (f) image[10+add] |= 1 << shift; else image[10+add] &= ~(1 << shift); | |
if (g) image[add] |= 1 << shift; else image[add] &= ~(1 << shift); | |
} | |
/** | |
* Print a character as a seven segment display image. | |
* | |
* @param c: character to print | |
* @param pos: position to display character on | |
*/ | |
void print_char(char c, byte pos) | |
{ | |
switch (c) | |
{ | |
case '0': | |
case 'D': | |
case 'O': | |
show_digit(pos, true, true, true, true, true, true, false); | |
break; | |
case '1': | |
show_digit(pos, false, false, false, false, true, true, false); | |
break; | |
case '2': | |
show_digit(pos, true, false, true, true, false, true, true); | |
break; | |
case '3': | |
show_digit(pos, true, false, false, true, true, true, true); | |
break; | |
case '4': | |
show_digit(pos, false, true, false, false, true, true, true); | |
break; | |
case '5': | |
show_digit(pos, true, true, false, true, true, false, true); | |
break; | |
case '6': | |
show_digit(pos, true, true, true, true, true, false, true); | |
break; | |
case '7': | |
show_digit(pos, true, false, false, false, true, true, false); | |
break; | |
case '8': | |
case 'B': | |
show_digit(pos, true, true, true, true, true, true, true); | |
break; | |
case '9': | |
case 'g': | |
show_digit(pos, true, true, false, true, true, true, true); | |
break; | |
case 'A': | |
case 'a': | |
show_digit(pos, true, true, true, false, true, true, true); | |
break; | |
case 'b': | |
show_digit(pos, false, true, true, true, true, false, true); | |
break; | |
case 'c': | |
show_digit(pos, false, false, true, true, false, false, true); | |
break; | |
case 'd': | |
show_digit(pos, false, false, true, true, true, true, true); | |
break; | |
case 'e': | |
case 'E': | |
show_digit(pos, true, true, true, true, false, false, true); | |
break; | |
case 'f': | |
case 'F': | |
show_digit(pos, true, true, true, false, false, false, true); | |
break; | |
case 'h': | |
show_digit(pos, false, true, true, false, true, false, true); | |
break; | |
case 'i': | |
show_digit(pos, false, false, true, false, false, false, false); | |
break; | |
case 'j': | |
case 'J': | |
show_digit(pos, false, false, true, true, true, true, false); | |
break; | |
case 'k': | |
show_digit(pos, false, true, true, true, false, false, true); | |
break; | |
case 'l': | |
case 'L': | |
show_digit(pos, false, true, true, true, false, false, false); | |
break; | |
case 'M': | |
case 'N': | |
show_digit(pos, true, true, true, false, true, true, false); | |
break; | |
case 'm': | |
case 'n': | |
show_digit(pos, false, false, true, false, true, false, true); | |
break; | |
case 'o': | |
show_digit(pos, false, false, true, true, true, false, true); | |
break; | |
case 'p': | |
case 'P': | |
show_digit(pos, true, true, true, false, false, true, true); | |
break; | |
case '-': | |
show_digit(pos, false, false, false, false, false, false, true); | |
break; | |
} | |
} | |
/** | |
* Display an integer. | |
*/ | |
void print_int(int number) | |
{ | |
if (number < 0) | |
{ | |
print_char('-', 0); | |
number = -number; | |
} | |
else | |
{ | |
print_char('0'+((number / 10000) % 10), 0); | |
} | |
print_char('0'+((number / 1000) % 10), 1); | |
print_char('0'+((number / 100) % 10), 2); | |
print_char('0'+((number / 10) % 10), 3); | |
print_char('0'+(number % 10), 4); | |
} | |
/** | |
* Display a clock. | |
*/ | |
void print_time(unsigned long t) | |
{ | |
const byte minutes = t % 60; | |
const byte hours = t / 60 % 24; | |
print_char('0'+(minutes % 10), 4); | |
print_char('0'+(minutes / 10), 3); | |
print_char('0'+(hours % 10), 2); | |
print_char('0'+(hours / 10), 1); | |
} | |
void partition(byte pos, bool on) | |
{ | |
byte prefix; | |
switch (pos) | |
{ | |
case 0: | |
prefix = 10; | |
break; | |
case 1: | |
prefix = 2; | |
break; | |
case 2: | |
prefix = 0; | |
break; | |
case 3: | |
prefix = 6; | |
break; | |
case 4: | |
prefix = 4; | |
break; | |
case 5: | |
prefix = 12; | |
break; | |
} | |
if (on) | |
{ | |
image[prefix] |= B00010000; | |
} else { | |
image[prefix] &= B11101111; | |
} | |
} | |
void print_seconds(byte sec) | |
{ | |
partition(0, sec < 30); | |
partition(1, sec > 5 && sec < 35); | |
partition(2, sec > 10 && sec < 40); | |
partition(3, sec > 15 && sec < 45); | |
partition(4, sec > 20 && sec < 50); | |
partition(5, sec > 25 && sec < 55); | |
} | |
/** | |
* Setup routine | |
*/ | |
void setup() { | |
pinMode(kPinStb, OUTPUT); | |
pinMode(kPinClk, OUTPUT); | |
pinMode(kPinData, OUTPUT); | |
digitalWrite(kPinStb, HIGH); | |
digitalWrite(kPinClk, LOW); | |
digitalWrite(kPinData, LOW); | |
delay(200); // Delay 200 ms according to ET6202 manual | |
set_data_flags(false, false, false); | |
set_address(0); | |
set_display_mode(eDisplayMode10char7bit); | |
set_display_control(true, 7); | |
} | |
unsigned long startTime = millis(); | |
unsigned long offset = 0; | |
void loop() { | |
refresh_display(); | |
const byte key = poll_keys(); | |
if (key) | |
{ | |
bool modifier = false; | |
if (key & 0x08) | |
{ | |
modifier = true; | |
// Serial.write("Key 4"); | |
} | |
if (key & 0x01) | |
{ | |
// Serial.write("Key 5"); | |
offset += 1 + modifier * 59; | |
} | |
if (key & 0x02) | |
{ | |
// Serial.write("Key 3"); | |
offset -= 1 + modifier * 59; | |
} | |
if (key & 0x10) | |
{ | |
// Serial.write("Key 2"); | |
startTime = millis(); | |
} | |
delay(200); | |
} | |
unsigned long myTime = ((millis() - startTime) / 1000) / 60; | |
print_time(myTime + offset); | |
print_seconds(((millis() - startTime) / 1000) % 60); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Found the old board again, will tweak the gist a bit and then upload it again :)