HT1621 basic driver code

Hello everyone.
I have an IC named HT1621 and I want to drive it manually.
What it is? It has a fancy name but basically is a multiplexed LCD driver.
What I did so far... for 2 or even 3 months now, I tried different approaches. The most successful ones was 2 arduino libraries for this particular IC: from valerio and another one from MartyMacGyver. No problem with these libraries, I make my LCD work with both of them !
Why it took me so much time and I still didnt finish anything? I tried to reverse engineer both their code!
-The first one, from Valerio, was very cryptic, I managed to dig into the library code and translate it into manageable code probably 95% of it. I managed to discover the logic that is dealing with the -settings- of the chip, but the -data- to light up the LCD segments, I got stuck on something that didnt had any easy answer on the web so I give up on it: snprintf(localbuffer, 7, flags, num); - this snprintf is having some very cryptic arguments inside, very obscure functionality and I couldn't get pass over it. Although Im mentioning it here, Im not asking help about it ! Keep reading.
-the second library, from MartyMacGyver, was not made like a library per say, but more as a manageable code, exactly as my original intention. On this one I got stuck on sending the -settings- for the chip, while the -data- was very easy to send.
I tested everything by chopping off the unnecessary code, and leaving only the most direct code, potentially show the mechanics. But...with great insuccess.
----------.----------
-My question to you is to help me make the most basic send -settings- and -data- protocol for this chip. To open only one LCD segment ! Please look into those 2 libraries code as I did; I can send you my chopped off code, in the hope will speed up your progress.
Thank you ! and I hope we can make something in the end !

20231212_035942


20231206_190046 Copy

Not sure where you need help. For setting individual segments I have some code here: GitHub - BlinxFox/SB06128: Arduino library for the HT1621 based LCD module GS-SB06128

1 Like

-I tested your library and it works, in the sense it is sending some data to the HT1621 driver and then to the display itself. I changed the pin numbers to fit with my board wires, and after that I got something, but is random segments on the LCD since this is a very diferent display than your tested one. So the bottom line it is working !
-Now...
I want to send bytes of specific bits (0b001010010 for example) to open the settings of the IC to give me access to the LCD in the first place.
Then to send bytes of specific bits (0b001010010 for example) to write specific segments of the LCD digits.
But much-much more simple and to the bone. What you did there is very nice but I need this very basic code to use it also here in arduino for future tests but also using a EEPROM or even a PIC.
Thank you.

I think you can take the initialization from begin() and these functions and copy them to a new library:

void shiftOutBits(int count, uint16_t value);
void sendCommand(uint16_t cmd);
void sendData8(uint8_t address, uint8_t value);

did you search for this? That is a basic C/C++ function that is well documented and easily referenced on the web.

@Rintin, I'm using your code with an LCD from Aliexpress ( I included the link for it below the code and the pictures).

I tried using Valerio's code, but only got random digits to display. I used your code and was able to get repeatable segments to light up. I'll post my modified code that I used with your library below.

The issue I'm running into is that when I send a single 8 bit code, I get four segments that light up in my LCD.

My question is, is this an issue with my board and I should just order a new one? Or, should I try and change your library code to modify it to 32bits? I noticed the function called "SendData8." Is there a possibility that I could modify that function to send 32 bit data instead of 8 bit data?

Here's the code with pictures uploaded beneath the in the order they display:

/**
   Little test sketch for testing the
   GS-SB06128TTWU-A/R LCD display
   salvaged from an
   UPS (PowerWalker VI 650 LCD)

   The display is based on the HT1621


   Wire this modul up like this:

   Connector CN2 LCD     Pin Arduino
   1  ???
   2  5V                     5V
   3  CS                     D3
   4  !WR                    D2
   5  Data                   D5
   6  GND                    GND
   7  (nc)
   8  -> CN1
   9  -> CN1
*/

#include "sb06128.h"

#define PIN_CS 4
#define PIN_DATA 3
#define PIN_WR 2

Sb06128 display(PIN_DATA, PIN_WR, PIN_CS);

void setup() {
  display.begin();
  display.test();
  delay(100);
  display.clear();
  delay(100);
  display.test();
  delay(100);

  Serial.begin(9600);
}

void loop() {
  //display.test();
  delay(100);
  display.clear();
  delay(100);
  display.test(0B00010000); // Displays Low Half 8
  delay(1000);
  display.test(0B00000001); // Displays High Half 8
  delay(1000);
  display.test(0B00010001); // Displays 8 in last digit
  delay(1000);
  display.test(0B11111111); // Displays 8.8:8*8
  delay(1000);
  display.clear();
  delay(100);
  display.test(0B00000000000000000000000000000001); // Displays High Half 8
  delay(1000);

 
}



Link to LCD:
https://www.aliexpress.us/item/2252799815802718.html?spm=a2g0o.order_list.order_list_main.10.ff651802lGZTZ8&gatewayAdapt=glo2usa (no documentation, but figured it was worth including).

I was only able to upload 3 images, here's the last two images from the display sequence:


When the pattern are reproduceable the basic communication with the display should work. But the library has no clue how to map the segments to the display memory locations.

You have to create a map with which bit sets which segment. This code might help you with this:

for(int addr=0; addr < 8; addr++){
  for(int x=0; x<8; x++){
    send8(addr, 1<<x);
    delay(1000);
  }
  send8(addr, 0);
}

I think its easier to split the 32bit into 4 calls of send8().

uint32_t data;
send8(0, data & 0xff);
send8(1, (data >> 8) & 0xff);
send8(2, (data >> 16) & 0xff);
send8(3, (data >> 24) & 0xff);

That worked! I changed the sendData8 function to a public function and then used the code you posted (see below). Now it's cycling through each individual segment. Thank you!

I'll keep testing it for the next few days and see how it goes.

/**
   Little test sketch for testing the
   GS-SB06128TTWU-A/R LCD display
   salvaged from an
   UPS (PowerWalker VI 650 LCD)

   The display is based on the HT1621


   Wire this modul up like this:

   Connector CN2 LCD     Pin Arduino
   1  ???
   2  5V                     5V
   3  CS                     D3
   4  !WR                    D2
   5  Data                   D5
   6  GND                    GND
   7  (nc)
   8  -> CN1
   9  -> CN1
*/

#include "sb06128.h"

#define PIN_CS 4
#define PIN_DATA 3
#define PIN_WR 2

Sb06128 display(PIN_DATA, PIN_WR, PIN_CS);

void setup() {
  display.begin();
  display.test();
  delay(100);
  display.clear();
  delay(100);
  display.test();
  delay(100);

  Serial.begin(9600);
}

void loop() {
  //display.test();
  delay(100);
  display.clear();
  delay(100);
  for (int addr = 0; addr < 8; addr++) {
    for (int x = 0; x < 8; x++) {
      display.sendData8(addr, 1 << x);
      delay(1000);
    }
    display.sendData8(addr, 0);
  }
}

Looking at the test pattern you used:

display.test(0B00010000); // Displays Low Half 8
display.test(0B00000001); // Displays High Half 8
display.test(0B00010001); // Displays 8 in last digit
display.test(0B11111111); // Displays 8.8:8*8

I hope for a mapping similar to this:

sendData8(0, <segmentA> + <segmentE>);
sendData8(1, <segmentB> + <segmentF>);
sendData8(2, <segmentC> + <segmentG>);
sendData8(3, <segmentD> + <symbol>);

segmentA: 
  0b00000001 -> digit0
  0b00000010 -> digit1
  0b00000100 -> digit2
  0b00001000 -> digit3

segmentE: 
  0b00010000 -> digit0
  0b00100000 -> digit1
  0b01000000 -> digit2
  0b10000000 -> digit3

My LCD seems to be wired horizontally? When I run the code you suggested to map out the segments (the nested For loops), it cycles through all the B segments for each digit, then the A segments, then the D segments, then the C segments, then the F segments, then the E segments, then the symbols (points and degree symbol) and finally the G segment. In summary: A D C F E Sym G.

How and where would I go in the code to remap this? Could I change this in the "sb06128.cpp" file or the header file?

I've figured out a workaround to map a few digits in the furthest right digit on the display. For example, this code snippet displays a 1 and then a 3.

// Display 1 in furthest right digit display
uint8_t topData = 0b00000001;
uint8_t botData = 0b00010000;
uint8_t midData = 0b00000000;
display.sendData8(0, topData);
//delay(1000);
display.sendData8(1, botData);
delay(100);

display.clear();
delay(1000);

// Display 3 in furthest right digit display
topData = 0b00010001;
botData = 0b00010001;
midData = 0b00010000;
display.sendData8(0, topData);
display.sendData8(1, botData);
display.sendData8(3, midData);
delay(100);


display.clear();
delay(1000);

Thanks for all of your help with this by the way, Rintin! I am a complete novice when it comes to LCDs. It's been very interesting learning about bit shifting, etc.



Here's some images showing what I'm seeing. The First image is showing the F segment lighting up on the "third" digit (when counting from right to left as that's the sequence they light up in).

The other two are my workaround for getting a specific number to display. It seems like in order to display a four digit number, I would have to have thousands of this different workaround to correctly display, which is why I'm trying to figure out how to remap.

Thanks!

Yes, but it could be worse.

I think I would try something like this:
(Not tested... I hope I did not mess it up too much)

uint8_t digitLUT[10] = {
  // GECAxFDB
   0b01110111, // 0
   ..., // 1
   ...
};

void setDigit(uint8_t pos, uint8_t value){
  if(pos >= 4 || value >= 10)
    return;
  
  auto pattern = digitLUT[value];
  for(int a = 0; a < 4; a++){
    auto data = _displayData[a];
    bitWrite(data, pos, bitRead(pattern, a);
    bitWrite(data, pos+4, bitRead(pattern, a+4);
    sendData8(a, data);
  }
}

I had to change a few things, but I got it to output something. It's so close, it just seems like one of the segments is off by one digit. Here's the code I'm running and below is a picture of the result. I've only input 0-3 for the digitLUT. The rest will just display as zero.

/**
   Little test sketch for testing the
   GS-SB06128TTWU-A/R LCD display
   salvaged from an
   UPS (PowerWalker VI 650 LCD)

   The display is based on the HT1621


   Wire this modul up like this:

   Connector CN2 LCD     Pin Arduino
   1  ???
   2  5V                     5V
   3  CS                     D3
   4  !WR                    D2
   5  Data                   D5
   6  GND                    GND
   7  (nc)
   8  -> CN1
   9  -> CN1
*/

#include "sb06128.h"

#define PIN_CS 4
#define PIN_DATA 3
#define PIN_WR 2

Sb06128 display(PIN_DATA, PIN_WR, PIN_CS);

void setup() {
  display.begin();
  display.test();
  delay(100);
  display.clear();
  delay(100);
  display.test();
  delay(100);

  Serial.begin(9600);


}

void loop() {
  //display.test();
  delay(100);
  display.clear();
  delay(100);


  setDigit(1, 3);
  delay(100);
  display.clear();
  
}

uint8_t digitLUT[10] = {
  // GECAxFDB
  0b01110111,  // 0
  0b00100001,  // 1
  0b11010011,  // 2
  0b10010011,  // 3
  0b01110111,  // 4
  0b01110111,  // 5
  0b01110111,  // 6
  0b01110111,  // 7
  0b01110111,  // 8
  0b01110111   // 9

};

void setDigit(uint8_t pos, uint8_t value) {
  uint8_t _displayData[8];

  if (pos >= 4 || value >= 10)
    return;

  auto pattern = digitLUT[value];

  for (int a = 0; a < 4; a++) {
    auto data = _displayData[a];
    bitWrite(data, pos, bitRead(pattern, a));
    bitWrite(data, pos + 4, bitRead(pattern, a + 4));
    display.sendData8(a, data);
  }
}

Is only segment C affected?
I think we have to add a look up table to fix this.

I messed up, I put in the wrong binary for 3. I redid it and I'm getting all the digits to display correctly in the 1 position. I'm still getting the C segment to light up in the 3 position

/**
   Little test sketch for testing the
   GS-SB06128TTWU-A/R LCD display
   salvaged from an
   UPS (PowerWalker VI 650 LCD)

   The display is based on the HT1621


   Wire this modul up like this:

   Connector CN2 LCD     Pin Arduino
   1  ???
   2  5V                     5V
   3  CS                     D3
   4  !WR                    D2
   5  Data                   D5
   6  GND                    GND
   7  (nc)
   8  -> CN1
   9  -> CN1
*/

#include "sb06128.h"

#define PIN_CS 4
#define PIN_DATA 3
#define PIN_WR 2

Sb06128 display(PIN_DATA, PIN_WR, PIN_CS);

void setup() {
  display.begin();
  display.test();
  delay(100);
  display.clear();
  delay(100);
  display.test();
  delay(100);

  Serial.begin(9600);
}

void loop() {
  //display.test();
  delay(100);
  display.clear();
  delay(100);

  for (int i = 0; i < 10; i++) {
    setDigit(1, i);
    delay(500);
    display.clear();
  }
}

uint8_t digitLUT[10] = {
  // GECAxFDB
  0b01110111,  // 0
  0b00100001,  // 1
  0b11010011,  // 2
  0b10110011,  // 3
  0b10100101,  // 4
  0b10110110,  // 5
  0b11110110,  // 6
  0b00110001,  // 7
  0b11110111,  // 8
  0b10110101   // 9

};

void setDigit(uint8_t pos, uint8_t value) {
  uint8_t _displayData[8];

  if (pos >= 4 || value >= 10)
    return;

  auto pattern = digitLUT[value];

  for (int a = 0; a < 4; a++) {
    auto data = _displayData[a];
    bitWrite(data, pos, bitRead(pattern, a));
    bitWrite(data, pos + 4, bitRead(pattern, a + 4));
    display.sendData8(a, data);
  }
}

9 seems to be faulty...

I think the addresses for segment C are messed up.
What does this show?

for(int x = 0; x < 4; x++){
  setDigit(x, 8);
  delay(1000);
  display.clear();
}

Here's the full code:

/**
*/

#include "sb06128.h"

#define PIN_CS 4
#define PIN_DATA 3
#define PIN_WR 2

Sb06128 display(PIN_DATA, PIN_WR, PIN_CS);

void setup() {
  display.begin();
  display.test();
  delay(100);
  display.clear();
  delay(100);
  display.test();
  delay(100);

  Serial.begin(9600);
}

void loop() {
  //display.test();
  delay(100);
  display.clear();
  delay(100);


  for(int x = 0; x < 4; x++){
  setDigit(x, 8);
  delay(1000);
  display.clear();
}
}

uint8_t digitLUT[10] = {
  // GECAxFDB
  0b01110111,  // 0
  0b00100001,  // 1
  0b11010011,  // 2
  0b10110011,  // 3
  0b10100101,  // 4
  0b10110110,  // 5
  0b11110110,  // 6
  0b00110001,  // 7
  0b11110111,  // 8
  0b10110101   // 9

};

void setDigit(uint8_t pos, uint8_t value) {
  uint8_t _displayData[8];

  if (pos >= 4 || value >= 10)
    return;

  auto pattern = digitLUT[value];


  for (int a = 0; a < 4; a++) {
    auto data = _displayData[a];
    bitWrite(data, pos, bitRead(pattern, a));
    bitWrite(data, pos + 4, bitRead(pattern, a + 4));
    display.sendData8(a, data);
  }
}

And this is what I see:
IMG_9848.MOV.zip (5.7 MB)

The forum moved my trust level up, so I'm going to try and post a video. Oh good, it worked!

1 Like

Hmm.... not what I was expecting. Please take a video with the single segments from #8.

SegmentCycleLowRes.mov.zip (5.5 MB)

Here's the code (from post #8):

/**
   Little test sketch for testing the
   GS-SB06128TTWU-A/R LCD display
   salvaged from an
   UPS (PowerWalker VI 650 LCD)
*/

#include "sb06128.h"

#define PIN_CS 4
#define PIN_DATA 3
#define PIN_WR 2

Sb06128 display(PIN_DATA, PIN_WR, PIN_CS);

void setup() {
  display.begin();
  display.test();
  delay(100);
  display.clear();
  delay(100);
  display.test();
  delay(100);

  Serial.begin(9600);
}

void loop() {
  //display.test();
  delay(100);
  display.clear();
  delay(100);

  for (int addr = 0; addr < 4; addr++) {
    for (int x = 0; x < 8; x++) {
      display.sendData8(addr, 1 << x);
      delay(500);
    }
    display.sendData8(addr, 0);
  }
};

Let me know if posting the full code is annoying or takes up too much space, I just figure it's easier for copying and pasting.

Thanks again for all the help!

Let me know if you want to see anything else.