Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Big Look-up Table Page Problem

Status
Not open for further replies.

jpanhalt

Well-Known Member
Most Helpful Member
I have been wrestling with this look-up table all day. The table call returns a packed value for month and day when presented with the day number in the year. It works fine for all days tested (Jan 1, JUN 1, DEC 1, DEC 10, SEP 10, and SEP12) except SEP 11 (day 255 this year) for which it returns a zero (note: January starts with an extra "day," because there is no "zero" day). The cursor in simulation goes to the January "0" position. It is obviously something to do with the page.

I have tried a lot of things, including Tony Nixon's approach (PICList). Since the table starts at 0x400, adding CountL to (low)Table, as done in many of the approaches I have tried can't cause a rollover. So, I test CountH and increment PCLATH accordingly.

"GetPack" gets the packed data byte from the GetDate table.

I have considered doing things like adding a null at position 255 and increasing the call value to compensate, or alternatively, breaking the table into two tables, but I am hoping there is simply an error in my code that manifests itself at the end of the page. This may be a silly question, but it is the first time I have dealt with such a large table

Regards, John


Code:
GetDate                       ;leap year = set Flag0,1
;enter routine with day# in CountH and CountL
     bsf       Flag0,1        ;set leap year
     movlw     HIGH(256)      ;336 FOR TESTING DEC 1, leap year
     movwf     CountH         ;345 = DEC 10
     movlw     LOW(256)       ;153 = JUN 1,leap
     movwf     CountL         ;255 = SEP 11 FREEZES
                              ;254 = SEP 10
                              ;256 = SEP 12
;*******************************************************************************
<snip>
GetPack
     movf      CountL,w
     pagesel   GetDay
     btfsc     CountH,0        
     incf      PCLATH
;need to do high/low thing with CountH/L
     call      GetDay
    ; pagesel   $
     movwf     Month          ;temp store packed day-month result
     andlw     0x1F           ;mask off high 3 bits
     movwf     Day            ;unpacked day
     movf      Month,w        ;retrieve packed day-month
     andlw     0xE0           ;mask off lower 5 bits
     swapf     WREG,w
     lsrf      WREG,w
     movwf     Month          ;month unpacked
     nop
     nop


     ORG 0x400
GetDay
     addwf     PCL  ;movwf    PCL   ;brw 
Jan
     dt 0,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
     dt 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
Feb
     dt 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
     dt 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d 
Mar
     dt 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
     dt 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f 
Apr
     dt 0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f
     dt 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e
May
     dt 0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf
     dt 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf 
Jun
     dt 0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf
     dt 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde
Jul
     dt 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
     dt 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
Aug
     dt 0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f
     dt 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f 
Sep
     dt 0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f
     dt 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e
 
UPDATE: I think I have the answer -- a little sleep. Will update tomorrow, if my idea doesn't pan out.

John
 
Hi John,

One of the nice features in the "Enhanced Mid-Range" devices is the ability to use the FSR's to access either 'Data' or 'Program' memory. The mechanism requires FSR bit 15 to be set when you're accessing 'Program' memory but you'll find that the "movlw high(xxx)" instruction actually does that for you when the assembler recognizes that 'xxx' is in 'program' memory...

Code:
GetPack
        movlw   low(table-1)    ; setup for indirect access
        addwf   CountL,W        ;  "
        movwf   FSR0L           ;  "
        movlw   high(table-1)   ;  "
        addwfc  CountH,W        ;  "
        movwf   FSR0H           ;  "
        moviw   FSR0++          ; read byte from table
        movwf   Month           ;
        andlw   0x1F            ; mask off high 3 bits
        movwf   Day             ; save Day, 1..31
        lsrf    Month,W         ;
        swapf   WREG,F          ;
        andlw   0x03            ;
        movwf   Month           ; save Month, 0..7 ???
Code:
table
Jan
        dt 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
        dt 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
Have you considered using the 'DW' (define word) directive to store 14-bit values in a 'program' memory table? Perhaps store the month (1..12) in the upper six bits and store the date (1..31) in the lower eight bits?
 
Last edited:
Hi Mike, That is exactly what I was planning to do, based on my earlier experience with printing a large font to a GLCD. Your advice is always appreciated. I have been at it (and a few other details) since 0430 this morning. Time to get a fresh start tomorrow.

I will update tomorrow.

Best regards,

John
 
Hi John. At first glance a 14-bit table doesn't seem too costly. I'll bet you could make a simple macro to build the 14-bit 'DW' tables too.

Code:
GetPack
        banksel CountL          ; bank 0                                  |00
        movlw   low(table-1)    ;                                         |00
        addwf   CountL,W        ;                                         |00
        banksel EEADRL          ; bank 3                                  |03
        movwf   EEADRL          ;                                         |03
        banksel CountH          ; bank 0                                  |00
        movlw   high(table-1)   ;                                         |00
        addwfc  CountH,W        ;                                         |00
        banksel EEADRH          ; bank 3                                  |03
        movwf   EEADRH          ;                                         |03
        bcf     EECON1,CFGS     ; not 'config' memory                     |03
        bsf     EECON1,EEPGD    ; select 'program' memory                 |03
;       bcf     INTCON,GIE      ; disable interrupts                      |03
        bsf     EECON1,RD       ; initiate 'read'                         |03
        nop                     ; required 'nop'                          |03
        nop                     ;  "                                      |03
;       bsf     INTCON,GIE      ; enable interrupts                       |03
        movf    EEDATL,W        ;                                         |03
        banksel Day             ; bank 0                                  |00
        movwf   Day             ; save 'Day', 1..31                       |00
        banksel EEDATH          ; bank 3                                  |03
        movf    EEDATH,W        ;                                         |03
        banksel Month           ; bank 0                                  |00
        movwf   Month           ; save 'Month', 1..12                     |00
        return                  ;                                         |00
Code:
table
        dw 0x0101,0x0102,0x0103,0x0104,0x0105,0x0106,0x0107,0x0108,0x0109,0x010A
        dw 0x010B,0x010C,0x010D,0x010E,0x010F,0x0110,0x0111,0x0112,0x0113,0x0114
        dw 0x0115,0x0116,0x0117,0x0118,0x0119,0x011A,0x011B,0x011C,0x011D,0x011E
        dw 0x011F
 
Last edited:
If you're curious what is wrong with the code in your first post, it's that you assume PCLATH contains 4 when it enters the subroutine whereas it contains the high byte of the address of GetDate.

Edit, I missed that you call GetDay and so the value of PCLATH is always 4.

Mike.
 
Last edited:
Hi John,
This is what I think is happening. I think at the instruction ADDWF at location 0x400 the value of PCL has been incremented to point to the next instruction before the addition takes place. As a result adding 255 to 0x401 results in a PCL value of 0x00 so the instruction at 0x400 is executed again with the same result. So the program is in a tight loop. You could possibly add a test to correct the problem when the day number is 255. Note that the table entry for day 255 will be at location 0x500 so a boundary has been crossed.

Les.
 
I am up and refreshed. I have all day and more to work on it.
Mike-K8LH : My first effort will be the one using indirect addressing as you show in your first post. I have not played with EEPROM yet. That may be an approach worth learning. The processor is an enhanced mid-range, specifically the 12F1840 . I forgot to mention that.
Pommie: The table is set at 0x400, and I watch PCLATH in the simulator window. My comment to Les goes into more detail where I felt the problem was occurring.
Les Jones: That was exactly my theory. You can watch PCL do that increment in simulation. I tried various ways to avoid it, such as creating the call PCL/PCLATH in code before the table, adding a null that would never be called at the page boundary, and incrementing PCLATH one step before CountH advances in this section by testing CountL to see if it has reached 0xFF :
upload_2016-1-5_3-40-58.png

Such approaches seemed rickety; although, I am not above doing such "fixes" when all else fails. Enhanced indirect addressing seems fit for the problem, and I have had experience with it in making a table for GLCD large fonts.

BTW, This code is to decipher the WWVB time signal. A $10 wall clock is the easy solution, but is not nearly as stimulating.

Thank you all for the thoughtful help and suggestions.

Regards, John

EDIT: Mike-K8LH --- I just noticed your question marks where my packed month ends at "6". I ran out of bits in the 8-bit byte. On Day 153 in leap years or 152 in regular years (July 1), my code adds 6 to the value returned for the month. Your way using DW is much cleaner.
 
Last edited:
UPDATE:
With clear eyes and a little sleep, I got it to work by pre-incrementing PCLATH when an index of 255 was encountered. Now, I am free to play with K8LH's 14-bit table.
Again, thank you all for the help and time.
Here's the kludged, but working code for that section:
Code:
GetPack                       ;as posted on ETO 01.04.16
     movf      CountL,w
     pagesel   GetDay
     xorlw     0xff           ;test for 255
     btfsc     STATUS,2
     bsf       CountH,0       ;pre-increment CountH to force increment PCLATH
     btfsc     CountH,0       ;01.05.16 THIS FIX WORKS for day 255 (Sept 11) 
     incf      PCLATH
     movf      CountL,w   
     call      GetDay
    ; pagesel   $
     movwf     Month          ;temp store packed day-month result
     andlw     0x1F           ;mask off high 3 bits
     movwf     Day            ;unpacked day
     movf      Month,w        ;retrieve packed day-month
     andlw     0xE0           ;mask off lower 5 bits
     swapf     WREG,w
     lsrf      WREG,w
     movwf     Month          ;month unpacked
Regards, John
 
I wonder if you couldn't have just used something like this for the GetDay subroutine?

Code:
GetPack
        call    GetDay          ; get table[Count-1]
        movwf   Month           ;temp store packed day-month result
        andlw   0x1F            ;mask off high 3 bits
        movwf   Day             ;unpacked day
        movf    Month,w         ;retrieve packed day-month
        andlw   0xE0            ;mask off lower 5 bits
        swapf   WREG,w
        lsrf    WREG,w
        movwf   Month           ;month unpacked
Code:
GetDay
        movlw   high(table-1)   ; table address hi
        addwf   CountH,W        ; offset hi
        movwf   PCLATH          ;
        movlw   low(table-1)    ; table address lo
        addwf   CountL,W        ; offset lo
        skpnc                   ; overflow? no, skip, else
        incf    PCLATH,F        ; adjust hi
        movwf   PCL             ; jump (PCLATH:PCL)
Code:
        org     0x0400
table
Jan
        dt 0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f
        dt 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f
 
Last edited:
Hi Mike,
Of course that works fine and is similar to how some of the PICList examples adjusted PCLATH before going to the table. That didn't work for me, but now I know my mistake -- I had forgotten to make a "call" and simply included what is in the "GetDay" routine in-line with GetPack. Of course, RETLW goes to the stack and since I hadn't called "GetDay", the return address was wrong.
Lessons learned:
1) One doesn't need to actually call the table, you can just set PCL with in-line code and it goes there; and
2) When you do step 1, be sure to the stack knows where to go on the return, assuming the table is uses an retlw construct.

I should have recognized that error yesterday, but was too foggy. I will also start using Table-1 rather than adding a null. It is much cleaner. I am still going to pursue the 14-bit table, as it is simpler to unpack and avoids having to adjust months 7-12.

You have been a great help. Thank you.

John
 
UPDATE
Tested three working methods and compared the times in simulation with MPLab SIM:
1) 14-Bit table using EEDATH:L = 22Tcy (44 us @ 2 MHz)
2) 8-Bit table using FSR1H:L = 16 TCY (32 us)
3) 8-Bit table setting PCL/PCLATH = 22 Tcy (44 us)

The 8-bit methods did not include timing for the steps needed to identify whether day number was >June 30 (day 181 or 182 depending on leap year status) so the packed month for the second half of the year can be incremented by 6. With a rough estimate of the additional time needed for that adjustment, the 14-bit table read is comparable or even a little faster then 8-bit table reads. I will beusing the 14-bit table.

Thank you all for the help.

Now on to the final two WWVB frames to decipher (year and DST).

Regards, John
 
BTW, This code is to decipher the WWVB time signal. A $10 wall clock is the easy solution, but is not nearly as stimulating.
Interesting project, John.

How did you come to choose a WWVB project as opposed to a project using a cheapie Serial GPS module? Does it have something to do with your interest in radio, or did your interest in WWVB spark your interest in radio?
 
Hi Mike,

It was entirely my interest in radio -- I built my first transmitter (27.255 MHz, 1952-1953) in 4th grade for an RC plane . I did consider a GPS module, but it just didn't seem as fun to do. I am pretty close to posting an update but am not real happy with the part of my program that syncs with the WWVB start. It can take almost 5 minutes. I would like to get it to about half of that, i.e, 1 minute to identify the start of the sequence and another minute to capture a complete sequence of the six, 10-second frames. I am using a 12F683 to generate a simulated signal, so reception is not an issue.

Regards, John
 
Last edited:
That's very cool. May I ask which WWVB receiver you're using, and, how well does it work there near Cleveland?
 
No problem at all. You may have heard of the CMMR-6 receivers made by C-Max (https://www.sparkfun.com/datasheets/Wireless/General/CMMR-6P-A2-1.pdf ). Apparently, they are out of production; although, DigiKey still lists them as "non-stock" (**broken link removed** ). I called DigiKey and the service person was quite clear that they were not available and would not be on order.

I Googled and found that PV Electronics in the UK sells a similarly appearing receiver with a COB instead of IC: https://www.pvelectronics.co.uk/index.php?main_page=product_info&products_id=7 . The manufacturer is shown as Symtrik (symtrik.com). The main difference between Symtrik and CMMR-6 pictures is a non-populated SOIC-8 pattern on the Symtrik board. Pin 1 appears to go to VCC, Pin 8 goes to ground, Pin 5 goes to what appears to be the output transistor from the receiver. I have not carefully traced the circuit and do not know where Pin 4 goes. Is it MCLR for 12F6xx? I have not tried to contact that company yet. Here's a direct link to the Symtrik datasheet: https://www.pvelectronics.co.uk/rftime/SYM-RFT-XX.pdf The service from PV Electronics was OK. Transport and to a lesser extent shipping were not the fastest. USPS probably contributed to that delay significantly. It is a reputable company so far as I can tell and that receiver is just a very small part of its business. Compared to the option of destroying a wall clock, I liked the larger size, and I hope to be able to extract the carrier. In the Fall, I played around with building my own receiver based on several designs using common op-amps and a bandpass filter IC. I was receiving something, but decided it is better to start with a working receiver.

Reception with the standard ferrite antenna is sporadic during the afternoon and early evening in Cleveland. I got steady signal between midnight and 3 AM, but it was weak. The EMF from a Tek 210 'scope complete blanked it out. A much older CRT 'scope worked fine for seeing the demodulated signal. MikeML send me some links to active antennas, which might be very helpful.

Let me know, if you want any more details.

Regards,

John
 
UPDATE
Well, between Alabama and finishing my NewYear's ham, I have made a little progress.

Here is an image of a decoded, simulated WWVB signal. The signal was generated by a 12F683 and hard-wired to the receiver. The decoder and display driver is a 12F1840.
upload_2016-1-12_18-14-51.png


The asterisk will be used to indicate synchronization with WWVB within the previous 24 hours. The "S" means standard time ("D"= DST). That is the 258th day of a common year. My leap-year algorithm seems to work fine.

Now, for another question. From my reading, most "atomic clocks" use a 32.768 kHz crystal for the seconds and synchronize around midnight (no reference to Monk's classic intended). The alternative I am considering is an RTC module for the seconds. Cost is not significantly different. Programming will be a little more complex for the RTC. I am leaning toward the crystal but am open to other opinions at this time. Temperature range will be indoors, so will not exceed the 60°F to 90°F range. One second or less per day is acceptable.

John
 
If its any interest jp I've played with radio time signals too, I have built a few pic and arduino clocks using our msf and the german dcf, some of my clocks are weird.
I also have a frequency standard I sort of adapted from other designs, it uses msf wjich is also 60kc, however msf switches the carrier so 1hz harmonics are really bad, and atmospherics mess things up twice a day too.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top