View previous topic :: View next topic |
Author |
Message |
djsb
Joined: 29 Jan 2011 Posts: 36
|
Driver for PCE2111 LCD Duplex driver (64 segment) |
Posted: Thu Aug 04, 2022 5:43 am |
|
|
I'm a relative beginner with CCS and a complete beginner when it comes to writing device drivers. I'm using a PIC16F887 MCU and PCM 5.092.
I'd like to test an LCD frequency display board on my Revox B261 FM tuner.
It uses an old Mullard/Philips PCE2111 LCD Duplex driver (64 segment). It uses a serial protocol that predates I2C.
https://www.google.co.uk/url?sa=t&rct=j&q=&esrc=s&source=web&cd=&cad=rja&uact=8&ved=2ahUKEwj39t6wha35AhVUEsAKHXf9DqgQFnoECBkQAQ&url=https%3A%2F%2Fwww.eevblog.com%2Fforum%2Ftestgear%2Fphilips-pm3295-and-pm3295a%2F%3Faction%3Ddlattach%3Battach%3D205895&usg=AOvVaw1l2A7uxUsj6BkY1DHQeAAK
The LCD itself uses 4 off 14 segment alphanumeric digits 100.00. The 1 has 2 segments and the zero's have 14 segments each as they are used for station names as well as the actual frequency (which goes from 88.00 to 108.00)
I would like to be able to write a simple driver that can turn on the segments in a meaningful way(actually create the numbers AND light up a few of the extra segments). This is to test the hardware. Later I'd like to replace the original LCD with a newer OLED and process the serial data stream from the original MCU (which is mask programmed, so is irreplaceable).
I have some assembly code for a PLL chip which is on the same MCU bus as the display, but I need to trim it down a bit before I post it on here (it has other LCD and rotary encoder assembler code mixed in). Would this assembly code be useful? I'd just like a few pointers or examples that could get me started. I think it's mainly bit banging 3 or 4 pins in a certain order. The timing is important, so mixing in the assembly code in the C listing would probably help. I will post some assembler code over the weekend. I hope someone can get me started. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Thu Aug 04, 2022 6:32 am |
|
|
You are taking me back in time....
Cbus is not at all like I2C. It is not an open collector bus.
Critical question. What voltage is the PCE2111 running off?. Though this
supports 5v operation, it's normal voltage is 3v. If it is running off this
voltage, you would be better using a 3v PIC instead of the 16F887.
The drive is very simple. All you do is raise DLEN, then output 34 bits.
For each bit, just output the bit and pulse the clock high/low. Quite
slow. Allow 8uSec after outputting each bit before the clock, and
operate the clock for 2uSec, then wait another 10 after dropping it.
So you get about 1mSec for the entire transfer.
The leading bit is always a zero, then 32 data bits, and a single flag
bit that says whether this is to load to the high register or the low register.
Then drop DLEN.
Finally send one more clock after you have dropped this.
I'd just do a very simple 'clock' routine to generate the pulse on the clock
line with this sort of timing, then just output the data bits in turn calling
this routine.
When I last drove this, the Z80, was a new chip!... The Marconi lab still
existed only a few miles up the road. Used to go shooting in their indoor
range!.
So something like:
Code: |
#define DLEN PIN_xx
#define DATA PIN_yy
#define CLB PIN_zz //set to suit you
int32 low32 = 0x1111;
int32 high32 = 0x5555; //some suitable test values
void init(voios)
{
//call at start to ensure lines are low
output_low(DLEN);
output_low(CLB);
}
#inline
void clock()
{
//generate one bit clock
delay_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 first
output_high(DLEN);
delay_us(8);
//output 32bit value to either low or high register
output_low(DATA);
clock(); //first send a 0
for (ctr=0;ctr<32;ctr++)
{
if (value & mask)
output_high(DATA);
else
output_low(DATA);
clock();
mask*=2; //Modern compiler should optimise this to shift
}
if (lowhigh)
output_high(DATA);
else
output_low(DATA);
clock(); //clock out the bit to specify high/low register
output_low(DLEN);
clock(); //now clock this into the latches.
delay_us(8); //do not do anything else for 8uSec
}
void main(void)
{
init(); //ensure bus is initialised
delay_us(100)'
send(low32, 0); //load the low 32bits
send(high32, 1); //load the high 32bits.
}
|
You will need to have a character array giving what bit numbers have
to be set for each digit, but this should do the clocking of this to the
display. |
|
|
djsb
Joined: 29 Jan 2011 Posts: 36
|
|
Posted: Thu Aug 04, 2022 7:14 am |
|
|
Ttelmah,
Thanks for your very helpful reply.
Here is the schematic at the bottom of my post in the EEVBLOG forum
https://www.eevblog.com/forum/projects/14-segment-lcd-emulation-on-a-128x32-ssd1306-based-oled-display/msg4331803/#msg4331803
The voltage appears to be 3.1v. However, the CBUS pins have 47k resistors in series with them, so maybe this is a crude way of level shifting the 5V down to 3v or so. I've never tried this, I'd normally use proper level shifting on modern chips. Would a LV PIC version have 3.3v logic levels or are there special chips for this. I've only ever worked with 5v PICS.
Are there any post you would recommend on setting up a character array? I'll have a good read of the forum and peruse any example code I can find.
Then I'll make a start with toggling some pins and monitoring the pins on my logic analyser and/or oscilloscope. |
|
|
djsb
Joined: 29 Jan 2011 Posts: 36
|
|
Posted: Fri Aug 05, 2022 9:06 am |
|
|
Here is a reply to the post in EEVBLOG that show the screenshot of my Saleae Logic16 connected to Port B0,B1 and B2 of a PIC16F1847.
https://www.eevblog.com/forum/projects/14-segment-lcd-emulation-on-a-128x32-ssd1306-based-oled-display/
The Logic 16 is triggered from the master clear pin when I push the reset button on my development board. I can't post any screenshots on this forum so I have to use EEVBLOG for most of my documentation for this project. I can zoom into the waveforms closer if needed. Thanks. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 05, 2022 11:06 am |
|
|
Quote: |
Are there any posts you would recommend on setting up a character array?
|
The following link has code for a 14-segment lcd display. It has a digit array.
Scroll down in the code to where it says: Digit_Map[10]
http://www.ccsinfo.com/forum/viewtopic.php?t=33377&start=11 |
|
|
djsb
Joined: 29 Jan 2011 Posts: 36
|
|
Posted: Fri Aug 05, 2022 2:36 pm |
|
|
Thanks PCM Programmer. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sat Aug 06, 2022 3:39 am |
|
|
The 47R resistor is _not_ to allow higher drive voltages. It is there to
reduce reflection on the edges of the waveform. A PIC at 5.5v driving in to
the inputs will be breaking the specifications for the chip. Maximum input
voltage on any pin is supply+0.3v.
Either use a lower voltage PIC (the '3.3v' PIC's will usually support operation
down to voltages like 2v), or add your own dividers to the signals. Otherwise
damage may result.
A suitable divider would be something like 220R+330R to ground, which
will then give a nominal 3v max signal (the chip needs 2v). |
|
|
djsb
Joined: 29 Jan 2011 Posts: 36
|
|
Posted: Sat Aug 06, 2022 4:18 am |
|
|
Ttelmah wrote: | The 47R resistor is _not_ to allow higher drive voltages. It is there to
reduce reflection on the edges of the waveform. A PIC at 5.5v driving in to
the inputs will be breaking the specifications for the chip. Maximum input
voltage on any pin is supply+0.3v.
Either use a lower voltage PIC (the '3.3v' PIC's will usually support operation
down to voltages like 2v), or add your own dividers to the signals. Otherwise
damage may result.
A suitable divider would be something like 220R+330R to ground, which
will then give a nominal 3v max signal (the chip needs 2v). |
There is a 47K resistor on each input on the LCD board and a 3.3k resistor also in series with the output of the CBUS on the MCU board (not posted on this forum). Despite this, I will take a cautious approach and use a potential divider as you suggest when I test the board next week. I'll also have a proper read of the datasheet for the PCE2111. Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Sun Aug 07, 2022 10:15 am |
|
|
As you say, you didn't mention the other resistors...
Key is to work out what these were actually giving to the Cbus device.
Have fun, |
|
|
djsb
Joined: 29 Jan 2011 Posts: 36
|
|
Posted: Wed Aug 10, 2022 8:07 am |
|
|
Ttelmah,
I'd just like to thank you again for the help you've given me with the code. Today I tried out my spare Revox LCD board with my development board fitted with a PIC16F1847. I managed to get nearly ALL the digits and segments lit (well, you know what I mean). Now I just have to work through the mapping of the data to the actual segments and digits.
I'll do this first by decrementing/incrementing the data words slowly (probably by just pressing a switch or by sending the information via RS232) so that I can see and note down how everything works. Later I will experiment with the character array that you and PCM Programmer mentioned earlier. Thanks again.
David. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Wed Aug 10, 2022 9:45 am |
|
|
Well done. Stepping through is the way I'd go. Then you really will know
where everyhing is. |
|
|
djsb
Joined: 29 Jan 2011 Posts: 36
|
|
Posted: Fri Aug 26, 2022 7:37 am |
|
|
In preparation for creating a "receive" function to add to the sample code above (or as an entirely separate piece of code), what is the correct way of storing 2 off 32 bit words that are received serially? I have read on this forum that it is best to buffer serial data using a double buffer. I eventually want to feed the output of the DATA, DLEN and CLK lines of the tuner into my development board. The PIC16F1847 will then spit out the binary data word over a RS232 link connected to my PC. I'd also like to separate and store the LOAD bit and any other control bits present.
I could start by feeding the output of the sample code above BACK into another pin as a kind of loopback test. Are there any posts on the forum that cover a similar topic so that I can get some understanding of what to do?
I'm still working on the LCD mapping and will be for a while. This is going quite well. Thanks. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Fri Aug 26, 2022 7:51 am |
|
|
One critical keyword here. 'union'.
Look here, and in the manual, and in the examples.
Key is it allows you to (efficiently) have multiple ways to reference the
same block of data. So you can have for example an array of eight bytes,
that is also readable as two 32bit words. |
|
|
djsb
Joined: 29 Jan 2011 Posts: 36
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19506
|
|
Posted: Mon Aug 29, 2022 4:09 am |
|
|
The first one is the way to go.
The second one is talking about how to take individual bytes 'out' of a
larger value. Not putting bytes together to form a larger value. It is also
much less efficient than using the union to do this.
Make 8, and make32 can also be used, but the union is the 'general' C
way of doing this (the make functions are CCS only), and the handling of
unions is as efficient as using these.
I was visualising that you might want to make the union hold two copies
of everything, so it can do your buffering as well. |
|
|
|