PIC18F2455 issue with timer0 generated clock - Page 1
Forum section: electronics / general

author: pyroesp
author_rank: Regular Contributor
timestamp: April 28, 2015, 05:49:26 pm
content: Hi all,A few weeks ago I scored a Planar low power 320x256 electroluminescent display (datasheet) from work. (This is what it looks like :http://gkdlcd.en.ecplaza.net/sitebuilder/images/md320.256-71e.jpg)From the datasheet you'll see it has a CLOCK, HSYNC, VSYNC, VID (even pixel column) and TVID (odd pixel column) input.The HSYNC being a low pulse of 4*Tclock and a high pulse of 320*Tclock.The VSYNC being a low pulse of at least 70µs and a high pulse of 256*Thsync.I first started with the idea of having 50fps, but after making a few calculations I just can't do it. I need a clock higher than 4MHz.So I went for a 10Hz refresh rate, which should give me a Tclock of 1.205µs or 830kHz.Code:Tvs = 1/10 = 100msTvs = Tvs_low + Tvs_high = 70µs + 256 * TvsThs = (Tvs - 70µs) / 256 = 390.35µsTclk = Ths / 324 = 1.205µsI thought using the PIC18F2455 with PLL, which would give me 48MHz, would be enough to generate an 830kHz clock, but I can't get my timer interrupt past76.92kHz153.84kHz.If I set my timer0 register TMR0 to 241, the timer0 interrupt should be called every (256-241)/(48MHz/4) = 1.25µs.Now that I write this post, I toggle my output every interrupt so my output clock would be 2*((256-241)/(48MHz/4)) = 2.5µs or 400kHz, anyways that's not the point.The output frequency doesn't go up past TMR0 being higher than 225 and I don't know why. TMR0 set to 220 gives an output frequency of 75kHz, higher than that it's just 76.9kHz.I read the errata of the PIC18F2455 but there wasn't anything about timer0, and google couldn't help me.Any ideas why ?Attached is my source code. I have checked the config words and the PLL should be set correctly. I also checked the timer0 config bits but I'm pretty sure they're set correctly as well.

author: Andy Watson
author_rank: Super Contributor
timestamp: April 28, 2015, 05:59:36 pm
content: Quote from: pyroesp on April 28, 2015, 05:49:26 pmHow long does it take to service the interrupt ? (I'm guessing 2.5us)

author: JTR
author_rank: Regular Contributor
timestamp: April 28, 2015, 06:04:05 pm
content: First thing that came to my mind too...

author: pyroesp
author_rank: Regular Contributor
timestamp: April 28, 2015, 06:54:38 pm
content: Ah man, I hadn't thought of that...Looking at the PICs program memory there are 44 opcodes in total between the interrupt call pointer and it's RETFIE.Code:129 0100 B4F2 BTFSC INTCON, 2, ACCESS130 0102 AAF2 BTFSS INTCON, 5, ACCESS131 0104 D00D BRA 0x120132 0106 0E00 MOVLW 0x0133 0108 6ED7 MOVWF TMR0H, ACCESS134 010A 0EE1 MOVLW 0xE1135 010C 6ED6 MOVWF TMR0, ACCESS136 010E 94F2 BCF INTCON, 2, ACCESS137 0110 0E08 MOVLW 0x8138 0112 1A81 XORWF PORTB, F, ACCESS139 0114 A681 BTFSS PORTB, 3, ACCESS140 0116 D004 BRA 0x120141 0118 0E00 MOVLW 0x0142 011A 6E1E MOVWF 0x1E, ACCESS143 011C 0E01 MOVLW 0x1144 011E 6E1D MOVWF 0x1D, ACCESS145 0120 C00E MOVFF 0xE, TABLAT146 0122 FFF5 NOP147 0124 C00D MOVFF 0xD, TBLPTRU148 0126 FFF8 NOP149 0128 C00C MOVFF 0xC, TBLPTRH150 012A FFF7 NOP151 012C C00B MOVFF 0xB, TBLPTR152 012E FFF6 NOP153 0130 C00A MOVFF 0xA, PRODH154 0132 FFF4 NOP155 0134 C009 MOVFF 0x9, PROD156 0136 FFF3 NOP157 0138 C008 MOVFF 0x8, FSR2H158 013A FFDA NOP159 013C C007 MOVFF 0x7, FSR2160 013E FFD9 NOP161 0140 C006 MOVFF 0x6, FSR1H162 0142 FFE2 NOP163 0144 C005 MOVFF 0x5, FSR1164 0146 FFE1 NOP165 0148 C004 MOVFF 0x4, FSR0H166 014A FFEA NOP167 014C C003 MOVFF 0x3, FSR0168 014E FFE9 NOP169 0150 C002 MOVFF 0x2, PCLATU170 0152 FFFB NOP171 0154 C001 MOVFF 0x1, PCLATH172 0156 FFFA NOP173 0158 0011 RETFIE 1Looks like XC8 adds a lot of code too...You guys have any idea how I can get a higher output frequency ?Knowing that I still have to generate every frame I'm not sure the PIC18F2455 is the MCU to use here. Maybe a 32bit PIC ? Never used those before.Or maybe go with an Atmel MCU ?Anyways, thanks for the help guys.

author: Bruce Abbott
author_rank: Frequent Contributor
timestamp: April 29, 2015, 03:51:39 am
content: Quote from: pyroesp on April 28, 2015, 06:54:38 pmYour EL display needs to be be continuously refreshed at a high rate with precise timing. This is similar to producing a composite video signal.The PIC can do it, but you have to make every cycle count. Write the display code in assembler so that you don't waste cycles. Timing can then be adjusted precisely because each machine code instruction executes in a fixed number of cycles. The code will have a short sequence that transfers 2 pixels and pulses VCLK, repeated 160 times (loop unrolled to maximize clock frequency). At the end of each line it pulses HS (pulsing VCLK at the same time) and counts the number of lines remaining. At the end of the frame it pulses VS, then loops back to do the next frame.This will leave no time left to do anything else! Actually that is not quite true. If you are willing to accept a slightly lower clock frequency then you could allocate a few cycles in between each VCLK for other tasks, padding out with NOPs where necessary to keep the video timing constant. During horizontal sync and vertical blanking time you don't need to send pixel data, so even more cycles are available. You may also be able to stretch out the vertical blanking period to get lots of time at the end of each frame.According to the EL display datasheet you must keep VCLK going during HS, but it might not be necessary during vertical blanking. If that is true then you could put the whole display routine into a timer interrupt running at the frame rate, with your main code running in the foreground during the vertical blank period.Another way to get a faster VCLK might be to generate it in hardware using the CCP or MSSP module. You could then poll the appropriate register or output pin to determine when to send pixel data and sync pulses. It might even be possible to put the display into single pixel mode and use SPI to send both clock and pixel data.

author: pyroesp
author_rank: Regular Contributor
timestamp: April 30, 2015, 06:31:04 pm
content: I'm going to try inline assembly first to speed up the interrupt.If that's not good enough, I might go for an asm only code.Thanks for the help, will post a few PICs (see what I did there) when I get it to work.

author: bson
author_rank: Unknown
timestamp: May 02, 2015, 01:27:32 am
content: Why not generate a 2.5MHz clock internally (say FOSC 10MHz, prescaled by 4), output that on the clock/t0 output and use for VID/TVID. Then generate HSYNC using a PWM channel (via TMR2 probably?). VSYNC should be easy, just interrupt on the TMR2 period and count lines, then stop TMR2 and output VSYNC; when done fire it up again. Do you need to output video data also, or only generate timing?

author: Howardlong
author_rank: Super Contributor
timestamp: May 03, 2015, 12:17:51 pm
content: Quote from: pyroesp on April 28, 2015, 06:54:38 pmNot sure which version of the compiler you're using. Mine is 1.32 in PRO mode and generates the following (note also that there is a workaround implemented by the compiler for fast interrupts covered in the errata which is what the POP is about, the vector at 0x0008 does a CALL rather than a GOTO).Code:71: void interrupt isr(void)00F8 0006 POP72: {73: if (INTCONbits.TMR0IF && INTCONbits.TMR0IE)00FA B4F2 BTFSC 0xff2, 0x2, ACCESS00FC AAF2 BTFSS 0xff2, 0x5, ACCESS00FE D00C BRA 0x11874: {75: TMR0 = 225;0100 6AD7 CLRF 0xfd7, ACCESS0102 0EE1 MOVLW 0xe10104 6ED6 MOVWF 0xfd6, ACCESS76: INTCONbits.TMR0IF = 0;0106 94F2 BCF 0xff2, 0x2, ACCESS77: TGLBIT(PORTB, ELD_CLK);0108 0E08 MOVLW 0x8010A 1A81 XORWF 0xf81, F, ACCESS78: if (GETBIT(PORTB, ELD_CLK))010C A681 BTFSS 0xf81, 0x3, ACCESS010E D004 BRA 0x11879: period = 1;0110 0E00 MOVLW 00112 6E10 MOVWF 0x10, ACCESS0114 0E01 MOVLW 0x10116 6E0F MOVWF 0xf, ACCESS80: }81:82: return;83: }0118 0011 RETFIE 0x1As you can see the unnecessary context saves are not performed.However I agree with others regarding using the CCP.If you need to output data too, you will probably find the PIC18 to be too limited. An alternative might be either a PIC24 (with DMA) or a PIC32 and use the DMA channels.

author: pyroesp
author_rank: Regular Contributor
timestamp: May 03, 2015, 10:55:59 pm
content: I just wanted to try out a checker pattern of some sort.If I want to be able to display at faster fps I will probably go with a PIC32.I'm using XC8 v1.33 in free version mode.

author: Howardlong
author_rank: Super Contributor
timestamp: May 03, 2015, 11:03:09 pm
content: Quote from: pyroesp on May 03, 2015, 10:55:59 pmGood idea, plenty of oomph and DMA even on the 28pin jobs.

author: pyroesp
author_rank: Regular Contributor
timestamp: May 05, 2015, 10:01:57 pm
content: I just got a few samples of PIC32MX170F256B and PIC24F16KA301 in DIP package.