News:

;) This forum is the property of Proton software developers

Main Menu

Getting a digit (DIG) from a value that came from a lookup table

Started by Ecoli-557, Dec 15, 2024, 03:41 AM

Previous topic - Next topic

Ecoli-557

Hello All (again).
Starting to get a real handle on this compiler and thanks to all who have pointed me in the correct direction.
I am now wrestling with trying to get a DIGIT (DIG) from a lookup table.
This is what I have:
'   DspDig2 = LookUp PVersion Dig 1,[ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE]
    DspDig2 = LookUp PVersion Dig [ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE], 1
    DspDig3 = LookUp PVersion Dig 0,[ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE]
The remarked line is from PBP3 and I think I understand the docs so I changed to the 2nd un-remarked line.
Compiler barks at them both.
PVersion may be up to 2 decimal digits and I am trying to get each digit to go into its associated variable; DspDig2 and DspDig3 for later display on a LED display.
what am I doing wrong?

Solved:
    DspDig2 = LookUp PVersion, [ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE], Dig 1     
    DspDig3 = LookUp PVersion, [ZERO,ONE,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE], Dig 0
DIG goes at the END, live and learn.

charliecoutas

Hi there

Glad you got it working, but why have you put "], Dig 1"    at the end of the Lookup command?

Charlie

top204

Please remember, the Positron compilers are not PBP, and their operations and syntax are different.

Your example with the Dig at the end of the LookUp is not valid and will not produce the correct code, and will not implement a Dig operation, and I will alter the compiler to give a syntax error in the next update, because it should actually be creating one.

Also, using multiple LookUp commands in a program listing, each with the same contents, is wasteful of flash memory, and was the only way data could be stored in PBP, but not with the Positron comilers that have true flash memory storage and retrieval methods.

For exampple, looking at your code, I do not quite understand what the "ZERO", "ONE", "TWO" constants represent, but the same thing can be done much more efficiently using:


    Dim bValue    As Byte
    Dim bDspDig1  As Byte
    Dim bDspDig2  As Byte
    Dim bDspDig3  As Byte
    Dim bPVersion As Byte
'
' Create a flash memory data table of 8-bit values
'
    Dim VersionTable As Flash8 = 100, 101, 102, 103, 104, 105, 106, 107, 108, 109
      
'----------------------------------------------------------------------------
' The main program starts here
'
Main:
    bPVersion = 2                                               ' Look for the third item in the data table
    bValue = CRead8 VersionTable[bPVersion]                     ' Read the data item held in bPVersion from the flash memory table
    bDspDig3 = Dig bValue, 0                                    ' Extract digit 0 from the value
    bDspDig2 = Dig bValue, 1                                    ' Extract digit 1 from the value  
    bDspDig1 = Dig bValue, 2                                    ' Extract digit 2 from the value
   
    HRSOutLn Dec1 bDspDig1, ",", Dec1 bDspDig2, ",", Dec1 bDspDig3

So only one data table is used and read, and this saves both code space and time.

On a serial terminal, the above program will display: "1,0,2"

Other ways could also be implemented using a procedure to extract a version and return its value, or extract digits from a known flash memory table, such as:

    bPVersion = 2
    bDspDig3 = VerDig_Read(bPVersion, 0)                        ' Extract digit 0 from the flash memory table
    bDspDig2 = VerDig_Read(bPVersion, 1)                        ' Extract digit 1 from the flash memory table  
    bDspDig1 = VerDig_Read(bPVersion, 2)                        ' Extract digit 2 from the flash memory table
   
    HRSOutLn Dec1 bDspDig1, ",", Dec1 bDspDig2, ",", Dec1 bDspDig3

'----------------------------------------------------------------------------
' Read a value from a flash memory table and extract a digit from it
' Input     : pElement holds the flash memory data element to read
'           : pDig hold the digit to extract from the element's value
' Output    : Returns an integer digit read from the value
' Notes     : None
'
Proc VerDig_Read(pElement As Byte, pDig As Byte), Byte
    Dim MyTable As Flash8 = 100, 101, 102, 103, 104, 105, 106, 107, 108, 109 ' Create a flash memory data table
   
    Result = CRead8 MyTable[pElement]                           ' Read the data item in pElement from the flash memory table
    Result = Dig(Result, pDig)                                  ' Extract, and return, a digit from the value read
EndProc

Ecoli-557

Charlie-
I need to get just 1 digit from a 2 digit variable is why I used DIG.
Les, Thanks for sharing - it does not give an error and I thought I had it - but, you are correct - of course as it does NOT give me what I need.
I will study your example to understand it.

BTW, is there any easy way to get a 500ms on and off LED to flash using Timer0?  I have created and broken mine several times <grin>.

Regards to All!

Stephen Moss

Quote from: Ecoli-557 on Dec 15, 2024, 07:44 PMBTW, is there any easy way to get a 500ms on and off LED to flash using Timer0?  I have created and broken mine several times <grin>.
That depends on several things such as the speed of the timers Clock source and the size of the timer (8-bit or 16-bit, some are fixed others can be set to one or the other in one of the relevant the timers register).
You need to convert the timer clock frequency to its period by dividing 1 by the Frequency and then divide 500mS by that value to the equivalent timer count value.

If the required Timer count value is less then the maximum timer count (255 for 8 bit & 65535 for 16 bit) then you have to pre-load the timer with an offset value, so if for example you were using an 8 bit timer and the required count for 500mS at the relevant Timer clock frequency was 120, then you write 135 (255-120) to the Timer (i.e. Timer0 = 135). Then the timer will overflow 120 counts (500mS) later, triggering an interrupt.

However, if the required count for 500mS in bigger then your timer, for example 345 for an 8 bit timer, then you may have to use a Prescaller where available to divide the clock down, in this example a divide by two would be sufficient, that would turn you 345 count to 172 as the timer value is now updated every two clock ticks instead of on every clock tick. So you would now pre-load your timer with an offset value of 83 (255 - 172).

If you have a very fast timer clock and want a very long delay things can get a little messy for those who have not used timers before as you have then start counting the number of timer interrupts within you interrupt handler and/or using Postscallers to get your timer interrupt to trigger at approximately the correct time interval.

Once you have calculated you timer count and Prescaller values, you have to enable the timer interrupt and usually the Global interrupt enable (GIE) as well, and create a Hardware interrupt handler subroutine (see the Positron user manual) within which, in your case you would write the code that toggles the state of the pin connected to the LED, re-write you offset value to the Timer and clear the relevant Timer interrupt flag, so something along the general lines of...
[Set device Fuse configuration & Declare its Xtal Frequency here]

On_Hardware_Interrupt Goto My_ISR   'Define Interrupt handler

[Setup Timer and enable it, also setup the interrupt enable bits here]

[Main Program Code here]

My_ISR:
Context_Save

If Tmr0_IF = 1 then  'Check if Timer0 Interrupt was triggered (If-Then-EndIf not necessary if the Timer0 interrupt is the only interrupt you have enabled)
Toggle PortB.0       'Turn LED On/Off
Tmr0 = 83            'Re-load Timer with offset value
Tmr0_IF = 0          'Clear Timer Interrupt Flag otherwise next interrupt will not be detected
EndIf

Context_Restore      'Exit Interrupt handler
You will need to check the applicable devices datasheet for the actual Timer register and interrupt flag names and interrupt enable bits you need to use as the above is just a rough guide.

Ecoli-557

The idea was a variable which may be 2 digits.  I would need to lookup from a table to get 1 of 2 the 2 digits in order to send to a LED controller.
I have changed that approach in favor of 2 different variables and no lookup.
I wanted to get to know this compiler's lookup practices.
Thanks for the input.
Now, om to multiple interrupts and how to deal with them.......

Ecoli-557

Thanks Stephen-
This is how I solved it last night:
Device = 18F67K40
Declare Xtal = 64
On_Hardware_Interrupt GoTo HB_Flash

 (other code here)

' Timer0 Constants stuff   
    Symbol TMR0IP = IPR0.5                  'Timer0 Interrupt Priority bit
    Symbol TMR0IF = PIR0.5                  'Timer0 Interrupt Flag bit
    Symbol TMR0IE = PIE0.5                  'Timer0 Interrupt enable bit
    Symbol T0EN = T0CON0.7                  'Timer0 Enable
    Symbol T016BIT = T0CON0.4              'Timer0 either 16 bit (1) or 8 bit (0)
    Symbol T0OUTPS = T0CON0.3              'Timer0 Postscaler - 4 digits

(other code here)

' Timer0 stuff for Heartbeat
    T0CON1 = 0b01011111                    'Timer0 source is TOsc/4 (not using HFINTOSC), not syncronized, 1:32768 prescaler
    TMR0IP = 1                              'Timer0 has High Priority
    TMR0 = 0                                'Clear TMR0 initially
    TMR0IF = 0                              'Clear the TMR0 overflow flag before enabling interrupt
    TMR0IE = 1                              'Timer0 interrupt enable
    INTCON = 0b10100000                    'Enable global interrupts
    T0CON0 = 0b00000000                    ' 8 bit timer and 1:1 Postscaler
    T016BIT = 0                            'Timer0 is a 8 bit timer

(Main code here and other subs)

'---  Heartbeat Interrupt  ---
HB_Flash:
    Context Save                            'Nifty..Save any variables or SFRs before the interrupt starts
    If TMR0IF = 1 Then                      'Timer0 Interrupt Flag
        Toggle Heartbeat                    'Yes. So. Toggle Heartbeat LED
        TMR0IF = 0                          'Clear the TMR0 overflow flag
    EndIf
    Context Restore                        'Restore any variables or SFRs and exit the interrupt   


Works fine as far as I can see