Skip to content

Instantly share code, notes, and snippets.

@powerswitch
Last active May 2, 2024 22:50
Show Gist options
  • Save powerswitch/79e91f8f2d5f311f0734438726b63486 to your computer and use it in GitHub Desktop.
Save powerswitch/79e91f8f2d5f311f0734438726b63486 to your computer and use it in GitHub Desktop.
Arduino code for ET6202 LED driver chip
// 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);
}
@powerswitch
Copy link
Author

Found the old board again, will tweak the gist a bit and then upload it again :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment