Help with mapping LCD segments to data word in LCD driver - Page 1
Forum section: electronics / projects

author: djsb
author_rank: Super Contributor
timestamp: August 13, 2022, 11:09:09 am
content: I have this code running on a PIC16F1847.Code:/*FILENAME:REVOX_B261_PCE2111_LCD_TEST1.CREVISION:0.1Date:05 August 2022Author: Original Ttelmah CCS INFO FORUM 04th August 2022 with contributions by David J S BriscoePurpose: This program is to test the Mullard/Philips PCE2111 Duplex 64 segment LCD driver on a Revox B261 FM tuner.Status: 10th August:All segments are lit (apart from STORE and ANT-Check LCD connections.Pin diagram;Target Controller - PIC16F1847;;RS232-WHITE------RA2 |118| RA1-----------;-----------------RA3 |217| RA0-----------;-----------------RA4 |316| RA7-----------;-----------------RA5 |415| RA6-----------;GND--------------VSS |514| VDD-----------+5V;PCE2111 DLEN-----RB0 |613| RB7-----------;PCE2111 DATA-----RB1 |712| RB6-----------;PCE2111 CLB------RB2 |811| RB5-----------;-----------------RB3 |910| RB4-----------;;NOTES:*/#include <16F1847.H>#fuses INTRC_IO, NOWDT, NOBROWNOUT, PUT,NOPROTECT,MCLR,NOLVP#use delay(clock=8000000)#use RS232(baud=9600, xmit=PIN_A2,ERRORS)//RS232 on Pin A2// Define pins for CBUS#define DLEN PIN_B0#define DATA PIN_B1#define CLB PIN_B2 //set to suit youint32 low32 = 0xFFFFFFFF; //ALL segments ONint32 high32 = 0xFFFFFFFF; ////int32 low32 = 0x00000000; //ALL segments OFF.//int32 high32 = 0x00000000; //.//int32 low32 = 0xFFDFFFFF; //STEREO (SEG 22)OFF (all others ON).//int32 high32 = 0xFFFFFFFF; ////int32 low32 = 0xFFFFFF7F; //25 OFF (SEG 8) ALL others ON.//int32 high32 = 0xFFFFFFFF; //.//int32 low32 = 0xFFFFFF7F; //25 OFF. POINT AND MHZ OFF//int32 high32 = 0xFFFFFF7F; ////int32 low32 = 0xFFFFFFFF; //75 OFF.25 AND 50 ON. 50 AND 75 SEG 32.//int32 high32 = 0x7FFFFFFF; ////int32 low32 = 0x7FFFFFFF; //50 OFF REST ON//int32 high32 = 0xFFFFFFFF; //void init(void){//call at start to ensure lines are lowoutput_low(DLEN);output_low(CLB);}#inlinevoid clock(){//generate one bit clockdelay_us(8);output_high(CLB);delay_us(2);output_low(CLB);delay_us(8);}void send(int32 value, int1 lowhigh){int ctr;int32 mask=1; //data is output LSb firstoutput_high(DLEN);delay_us(8);//output 32bit value to either low or high registeroutput_low(DATA);clock(); //first send a 0for (ctr=0;ctr<32;ctr++){if (value & mask)output_high(DATA);elseoutput_low(DATA);clock();mask*=2; //Modern compiler should optimise this to shift}if (lowhigh)output_high(DATA);elseoutput_low(DATA);clock(); //clock out the bit to specify high/low registeroutput_low(DLEN);clock(); //now clock this into the latches.delay_us(8); //do not do anything else for 8uSec}void main(void){int32 loop_cntr;for( loop_cntr = 0; loop_cntr < 0xffff; loop_cntr++){init(); //ensure bus is initialiseddelay_us(100);//low32--;send(low32, 0); //load the low 32bitssend(high32, 1); //load the high 32bits.//delay_us(100);//printf("Loop count: %8LX\r\n", loop_cntr);//printf("low32 value: %8LX\r\n", low32);delay_ms(1000);//printf("high32 value: %8LX\r\n", high32);printf("WORKING...\r\n");}}As you can see in the comments above, I have got some code turning on/off a few segments by random experimentation as followsCode:int32 low32 = 0xFFFFFFFF; //ALL segments ONint32 high32 = 0xFFFFFFFF; ////int32 low32 = 0x00000000; //ALL segments OFF.//int32 high32 = 0x00000000; //.//int32 low32 = 0xFFDFFFFF; //STEREO (SEG 22)OFF (all others ON).//int32 high32 = 0xFFFFFFFF; ////int32 low32 = 0xFFFFFF7F; //25 OFF (SEG 8) ALL others ON.//int32 high32 = 0xFFFFFFFF; //.//int32 low32 = 0xFFFFFF7F; //25 OFF. POINT AND MHZ OFF//int32 high32 = 0xFFFFFF7F; ////int32 low32 = 0xFFFFFFFF; //75 OFF.25 AND 50 ON. 50 AND 75 SEG 32.//int32 high32 = 0x7FFFFFFF; ////int32 low32 = 0x7FFFFFFF; //50 OFF REST ON//int32 high32 = 0xFFFFFFFF; //However, I'd like to get the digits working, and I'm struggling to understand how the data words relate to the segments. If I understood this then I'd be able to get the mapping done quicker. Can someone help me to understand how this works? Thanks.

author: Ian.M
author_rank: Super Contributor
timestamp: August 13, 2022, 12:29:11 pm
content: I assume you found a PCE2111 datasheet. If not, there's one here:https://www.eevblog.com/forum/testgear/philips-pm3295-and-pm3295a/?action=dlattach;attach=205895What's the problem? The mapping is documented on the schematic you attached.There are two columns, one for the PCE2111 A latches (pin BP1 (38) => LCD COM2 (26) ) and the other for the BN latches (pin BP2 (37) => LCD COM1 (52) ). Each segment is either described by name for the various annunciators or by digit number + segment letter for the four starburst digits and leading '1' - see LCD on schematic. Unfortunately, it isn't annotated which column is which set of latches so you'll have to figure out the CBUS bit 33 level for yourself and add column headings accordingly.

author: Andy Watson
author_rank: Super Contributor
timestamp: August 13, 2022, 01:05:23 pm
content: The only difficulty is the"ANT", which appears to be hard-wired.Also, you probably want to use unsigned ints - otherwise unexpected things might happen depending on the state of the most significant bit.

author: DavidAlfa
author_rank: Super Contributor
timestamp: August 13, 2022, 01:28:51 pm
content: Why create a new message? Better you continueyour existing thread, the segments were described there.Code:HighLow Value(32 bits)31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00Segments 32-01 0 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01Segments 64-33 1 64 63 62 61 60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33You can send the value in any format, ex. hexadecimal (You can use any convertex, ex.this one),or binary right away, but for 32 bit it'll quite long, ex. 0b111100001111100001111000011110000To display "12345":Display 1: bc = S22H (They're connected together)Display 2: abdehm = S21L S15H S25H S24H S16L S24LDisplay 3: abcdhm = S20L S9H S10H S12H S10L S13LDisplay 4: bcfhm = S2H S3H S7H S3L S6LDisplay 5: acdfhm = S17L S30H S28H S1H S30L S27LAs you see, everything is part of everything, you can't just write to a single digit without affecting others.So you must know all the segments beforehand, then prepare the data.In this case, after tidying, we have this (Might have some errors, lots of bits flying around):S30H S28H S25H S24H S22H S15H S12H S10H S9H S7H S3H S2H S1H0b00101001101000000100101101000111 = 0x29A04B47S30L S27L S24L S21L S20L S17L S16L S13L S10L S6L S3L0b00100100100110011001001000100100 = 0x24999224Finally:Code:send(0x29A04B47, 1);send(0x24999224, 0);High and low might be reversed, if looking weird try:Code:send(0x29A04B47, 0);send(0x24999224, 1);This all needs to be done using some sort of tables and parsing to make it efficient.

author: djsb
author_rank: Super Contributor
timestamp: August 13, 2022, 02:14:19 pm
content: Thanks everyone for your replies.I was going to add this to my existing thread, but I wanted the post to be more specific to the task to avoid confusion.I'll plough on with the mapping. I'm going to start with one digit and map the segments for numbers 0-9. Then I'll try moving the same numbers to another digit. Later I'll have to do letters as well, as the display shows letters to indicate stations.PS Can a moderator merge this thread with my previous related thread if preferred?https://www.eevblog.com/forum/projects/14-segment-lcd-emulation-on-a-128x32-ssd1306-based-oled-display/Thanks.

author: Ian.M
author_rank: Super Contributor
timestamp: August 13, 2022, 03:42:47 pm
content: I posted a 7 bit ASCII 14 segment starburst font table here:https://www.eevblog.com/forum/projects/vacuum-fluorescent-display-multiplexing-problem/msg1034886/#msg1034886As usual for starburst displays upper and lower case are identical. At the time I said:QuoteYou need a 64 bit buffer in RAM for the display, organized as two 32 bit words for the A and B latches (or possibly simply as eight bytes). You also need a lookup table for which segment goes where, organized by digit position. Due to limited program memory, its probably best to store the segment position as two nibbles (as nibble swaps are efficient on PIC16) in a byte, using one as an index into the display buffer and the other as an index into a lookup table of one bit set bytes (as PIC16 doesn't have a barrel shifter):Code:const uint8_t mask1bit={0b00000001,0b00000010,0b00000100,0b00001000,0b00010000,0b00100000,0b01000000,0b10000000};To write a character to the display at position x, you look up the segment pattern in the font table, then loop through the pattern word one bit at a time, looking up each segment in your position table to get a character position specific byte and bit no. converting the bit no. to a mask from the above array, and if the bit in the segment pattern was 1, ORing the mask with the buffer byte, otherwise, it was 0 so invert the mask and AND it.

author: djsb
author_rank: Super Contributor
timestamp: August 13, 2022, 03:53:26 pm
content: Thanks Ian.M,This post in the CCS Forum was also recommended to mehttps://www.ccsinfo.com/forum/viewtopic.php?t=33377&start=11So, a lot of work ahead of me, but I'm making some progress. And most importantly I'm learning new stuff and that's really the whole point.I'll pop back later if I get stuck. Thanks everyone again.

author: Ian.M
author_rank: Super Contributor
timestamp: August 13, 2022, 03:58:00 pm
content: Edit above: fixed the mask1bit[] lookup table.I also forgot to mention the final step: After you've written all the characters you want to the buffer array using the above segment at a time method, you finally send the buffer to the PCE2111, as two CBUS transfers of half the buffer at a time, to update the A and B latches respectively.