Custom LCD & Arduino

In the past I've used Arduinos for smaller projects, mostly finding pieces of code on the internet and adapting them to my needs.
I have always controlled external hardware such as displays with existing libraries.

But now I'm facing a challenge that I haven't had before:

I have a lot of individual LCD's (15 numbers, 22 prompts) which I want to test for functionality first. So switching all symbols and signs on and off and possibly a quick counting up of the number displays is the challenge.
As simple as that may sound - I don't know how and where to start.

Maybe someone can give me a little tip to start with.
First I have to wire the display correctly.

The documentation says:
Three lines serial interface (B type)
1 - CS: Serial shift pulse input
2 - CLK: Serial shift pulse input
3 - DI:Serial data input
4 - VSS:Power ground
5 - VDD:Power anode
6 - BLA: Backlight cathode
7 - BLK: Backlight anode

Pins 1 - 3 I don't really know. When using a library I would define the pins and assign them to the library, but like this..?
Pins 4 - 7 should be self explanatory.

So, every idea, every "jump start" is welcome. I enclose the documentation for the display, maybe someone already had a similar case.
Sorry - no documentation yet, because I'm not allowed...

I'd say your lcd is SPI, based on pins 1 - 3.
1 - Chip Select for SPI.
2 - CLK would go to your board SPI SCLK pin.
3 - DI would got to your board SPI MOSI pin.

I'll try that and those are exactly my thoughts.
Then just ask me how "something" to send to the display. The documentation pinout includes this table:

1 Like

a first step is that you should provide ALL information of that display.
That includes:

  • any clear product name/identity to make it more obvious than "a LCD"
  • a link to the product or a picture showing front and back to let the community identify the display
  • a link to the datasheet of that display, if you have a documentation - post it!
1 Like

As I mentioned before am I not allowed to post any uploads. Don't understand why new guests are handicapped by this setting - if I would want to send spam I would send text spam...
So, unfortunately documentation I can't share until I'm not allowed to upload files.

By the way - I'm also not allowed to post more than pic in one post. So I'll split the information from the docs I have

As I also mentioned before this is a custom display, so you'll not find any documentation or type at the internet. The only thing I've got is the PIN-out table from my last post, the "main technical data" which are:

and the display drawing itself - which I think is not taht important to get the display running - but anyway:

and

These information is more or less the whole documentation I have...

After a while playing around I tried to talk to the display like a ht1621.
Found an example coder here:

HT1621 Example

After changing the 3 singanl pins I'got some weired singns on my display where the author expects 543210 on his display. But it showed me that I'm on the right way...

During reset the full display sysmbols are visible for a short moment.

The next I'll try to understand the code and change it matching my display and showing all numbers and signs like during reset.
I'd still appreciate some help as it would probably speed things up a lot :rofl:

Looking at the datasheet might help (https://www.holtek.com/documents/10179/116711/HT1621v321.pdf)

What does the display show when you write the following to it?

  Write_1621( 0,0b00000001);
  Write_1621( 2,0b00000010);
  Write_1621( 4,0b00000100);
  Write_1621( 6,0b00001000);
  Write_1621( 8,0b00010000);
  Write_1621(10,0b00100000);
  Write_1621(12,0b01000000);
  Write_1621(14,0b10000000);

Now I'm able to post Files here!
So the full documentation I have comes here:
A32x FCU display -- confirmed.pdf (224,8 KB)

What i've figured out is this code, which turns all numbers an segments on and off.

#define CS   5  //Pin 2 as chip selection output
#define WR   6  //Pin 3 as read clock output
#define DATA 7  //Pin 4 as Serial data output
 
#define CS1    digitalWrite(CS, HIGH) 
#define CS0    digitalWrite(CS, LOW)
#define WR1    digitalWrite(WR, HIGH) 
#define WR0    digitalWrite(WR, LOW)
#define DATA1  digitalWrite(DATA, HIGH) 
#define DATA0  digitalWrite(DATA, LOW)
 
#define uchar   unsigned char 
#define uint    unsigned int 
 
#define  ComMode    0x52  
#define  RCosc      0x30  
#define  LCD_on     0x06 
#define  LCD_off    0x04 
#define  Sys_en     0x02 
#define  CTRl_cmd   0x80
#define  Data_cmd   0xa0

const char num[]={0x7D,0x60,0x3E,0x7A,0x63,0x5B,0x5F,0x70,0x7F,0x7B,0x77,0x4F,0x1D,0x0E,0x6E,0x1F,0x17,0x67,0x47,0x0D,0x46,0x75,0x37,0x06,0x0F,0x6D,0x02,0x00,};
char dispnum[6]={0x00,0x00,0x00,0x00,0x00,0x00};
 
void SendBit_1621(uchar sdata,uchar cnt) 
{ 
  uchar i; 
  for(i=0;i<cnt;i++) 
  { 
    WR0;
    if(sdata&0x80) DATA1; 
    else DATA0;
    WR1;
    sdata<<=1; 
  } 
}
 
void SendCmd_1621(uchar command)
{ 
  CS0; 
  SendBit_1621(0x80,4);   
  SendBit_1621(command,8);
  CS1;                     
}
 
void Write_1621(uchar addr,uchar sdata)
{ 
  addr<<=2; 
  CS0; 
  SendBit_1621(0xa0,3);    
  SendBit_1621(addr,6);     
  SendBit_1621(sdata,8);    
  CS1; 
}
 
void HT1621_all_off(uchar num)
{
  uchar i; 
  uchar addr=0; 
  for(i=0;i<num;i++) 
  { 
    Write_1621(addr,0x00); 
    addr+=2; 
  } 
}
 
void HT1621_all_on(uchar num)
{
  uchar i; 
  uchar addr=0; 
  for(i=0;i<num;i++) 
  {
    Write_1621(addr,0xff); 
    addr+=2; 
  } 
}
 
void Init_1621(void)
{
  SendCmd_1621(Sys_en);
  SendCmd_1621(RCosc);    
  SendCmd_1621(ComMode);  
  SendCmd_1621(LCD_on);
}    
 
void setup() {
  pinMode(CS, OUTPUT); // 
  pinMode(WR, OUTPUT); // 
  pinMode(DATA, OUTPUT); //
  CS1;
  DATA1;
  WR1;
  delay(50);
  Init_1621();
}
 
void loop() {
  HT1621_all_on(16);
  delay(5000);
  HT1621_all_off(16);
  delay(1000);
 }

The same happens whe I send your suggested code to the display

Write_1621( 0,0b00000001);
Write_1621( 2,0b00000010);
Write_1621( 4,0b00000100);
Write_1621( 6,0b00001000);
Write_1621( 8,0b00010000);
Write_1621(10,0b00100000);
Write_1621(12,0b01000000);
Write_1621(14,0b10000000);

I was hoping for the first 8 digits to turn on one segment.

Sorry, my last posting was wrong!
I forgot to clear the display before sending your code. After a "clean & blank" display you code produces that:

And you are right - that are 8 elements, but unfortunately not on one segment...

Its better for a lookup table when its not the same segment.

Does this count up on the first 3 digits?

//  AA
// F  B
// F  B
//  GG
// E  C
// E  C
//  DD
//
//  .FGEABCD
static const uint8_t digits[10] = {
  0b01011111, // 0
  0b00000110, // 1
  0b00111101, // 2
  0b00101111, // 3
  0b01100110, // 4
  0b01101011, // 5
  0b01111011, // 6
  0b00001110, // 7
  0b01111111, // 8
  0b01101111, // 9
};


byte c = 122;
void loop() {
  c++;
  auto e1 =  c        % 10;
  auto e2 = (c /  10) % 10;
  auto e3 = (c / 100) % 10;
  
  Write_1621(0,digits[e3]);
  Write_1621(2,digits[e2]);
  Write_1621(4,digits[e1]);
  
  delay(2000);
}
1 Like

cool - it does!
Starting from 122 on the first three digits from left!

So each row of the table in #3 is a 7-segment starting from the left, and each column is a segment, and the Z8 at 14,D0 is the "V/S" prompt. Cool.

And now for the tricky part... update symbols and digits without overwriting the other

//  AA
// F  B
// F  B
//  GG
// E  C
// E  C
//  DD
//
//  .FGEABCD
static const uint8_t digits[10] = {
  0b01011111, // 0
  0b00000110, // 1
  0b00111101, // 2
  0b00101111, // 3
  0b01100110, // 4
  0b01101011, // 5
  0b01111011, // 6
  0b00001110, // 7
  0b01111111, // 8
  0b01101111, // 9
};

byte memory[16] = {0};
void updateMem(byte addr, byte value, byte mask){
  auto tmp = memory[addr] & ~mask;
  tmp |= value & mask;
  memory[addr] = tmp;
  Write_1621(addr * 2, tmp);
}

void setDigit(byte pos, byte value){
  updateMem(pos, digits[value], 0x7F);
}

void setSymbol(byte sym, bool enable){
  byte b = sym & 0x07;
  byte addr = sym >> 4;
  byte value = enable ? 0xff : 0x00;
  updateMem(addr, value, bit(b));
}

// lower 3 bit for the bit position
// upper 4 bit for the address
#define SYM_Z22 0x07
#define SYM_Z21 0x17
#define SYM_Z20 0x27

#define SYM_Z1  0xF0

#define SYM_Z13 0xF4

#define SYM_Z10 0xF7

byte c = 122;
void loop() {
  c++;
  auto e1 =  c        % 10;
  auto e2 = (c /  10) % 10;
  auto e3 = (c / 100) % 10;
  
  bool en = true;
  setSymbol(SYM_Z22, en);
  setSymbol(SYM_Z21, en);
  setSymbol(SYM_Z20, en);

  setDigit(0, e3);
  setDigit(1, e2);
  setDigit(2, e1);

  setSymbol(SYM_Z1 , en);
  setSymbol(SYM_Z13, en);
  setSymbol(SYM_Z10, en);
  delay(1000);

  en = false;
  setSymbol(SYM_Z22, en);
  setSymbol(SYM_Z21, en);
  setSymbol(SYM_Z20, en);
  setSymbol(SYM_Z1 , en);
  setSymbol(SYM_Z13, en);
  setSymbol(SYM_Z10, en);
  delay(1000);
}
1 Like

I'll try it this evening - but thanks a lot in advance!
Give me some time to understand the code and nit just copy it...

of course I couldn't wait until tonight...

This comment did the job!

// lower 3 bit for the bit position
// upper 4 bit for the address

At least I was able to define the remaining symbols on the upper line and let them blink too.
I'll go thrue the other symbols and will try then to get 4 & 5 digit numbers counting too.
Again 1000 thanks and I'll keep you informed...