I have a working Interrupt Menu on an 18F2525, but need some help improving it. My program is constantly listening for data coming in on serial line via RB2, converting the binary data to usable information, and then either displaying that data, or writing the raw data to EEPROM. Since the data could come in as fast as every 100ms, I want to use an interrupt to manage the menu selection vs just polling for a button push. (but am open to simpler ways, certainly!)
The menu/interrupt needs to allow the user to change what is happening with as little disruption to the data read - store routine as possible. I don't need to get too fancy, because a few lost packets is OK, but I do want to allow user to select:
1. View 1 of data - eg long/lat
2. View 2 of data - eg speed/hdg
3. View 3 of data - eg volt/temp
AND,
4. Start recording data to EEPROM
5. Stop recording data to EEPROM
6. Play recorded data from EEPROM out the Serial port (Dump)
7. Erase EEPROM
Ideally, I'd use 2-3 buttons - 1/2 would scroll(up/down) throgh menus displayed on the LCD, the other would 'Select' the current view so the user can skip past those not wanted, and would then display that menu info on the LCD.
The routine I use now is a simple Interrupt with T1CON. I don't think this will do it for the more complex menu that I need. Here is what I have setup for the 18F2525:
@ __CONFIG _CONFIG1H, _OSC_INTIO67_1H
@ __CONFIG _CONFIG2H, _WDT_ON_2H & _WDTPS_128_2H
@ __CONFIG _CONFIG3H, _PBADEN_OFF_3H & _MCLRE_OFF_3H
@ __CONFIG _CONFIG4L, _LVP_OFF_4L & 0bfh ;_XINST_OFF_4L
'
' -----[ Includes/Defines ]---------------------------------------------------------
OSCCON=%01111000
DEFINE OSC 8
While OSCCON.2=0:Wend
include "modedefs.bas" 'include serout defines
'define loader_used 1 Used for bootloader only
ADCON0 = %00110000 ' turn off - select port AN12 (nothing)
ADCON1 = %00001111 ' turn portA to digital I/O (same as dec 15)
CMCON = $07 ' turn off
HLVDCON = %00000000 ' turn off
CVRCON = $00000000 ' turn off
SSPCON1 = %11011100 ' supposed to be turning on I2C
SSPCON2 = %01111000 ' supposed to be turning on I2C
INTCON = %11110000 ' TG guess at 2525 interrups for all INT pins
INTCON2= %01110101 ' rising edge of INT0,1,2 RB0,1,2
RCON = %10000000 ' no priority interrups
T1CON = %11000000 'Timer1 1:1 prescale.
...
variables, etc,
...
' ----- starting here ---------------------------------------------------
On Interrupt Goto ProcedureSwitcher
Bmenu = 1
ReStart:
TMR1H = 0 ' Clear time counts before Timer1 re-start
TMR1L = 0 ' Clear time counts before Timer1 re-start
PIR1.0 = 0 ' CLear over-flow flag before enable
T1CON.0 = 1 ' Turn Timer1 back on before entry into MainProcedure
Main:' ****** [Main Program Loop] ************************************************** ***************
wp=wp+1
gosub getdata ' go get data from radio
if stflag = 1 then
gosub storedata ' store ss data to EEROM if flag is on
endif
gosub calcvalue ' calculate values
if wp > 15 then
gosub waypoint ' ALWAYS put out a waypoint signal on the line (4800b)
endif
Select Case Bmenu ' display and act accordingly - driven from interrupts
case 1
gosub dis1 ' display information
Case 2
gosub dis2 ' display lat/long
Case 3
gosub dis3 ' display speed volts
Case 4
gosub dis4 ' Display Alt
Case 5
gosub dis5 ' RSSI - radio strenght
Case 6
gosub dis6 ' output memory - 9600b - same line as GPS is on
Case 7
gosub dis7 ' erase memory, reset address to 0
Case 8
gosub dis8 ' Start Recorder - set stflag to 1
Case 9
gosub dis9 ' Stop Recorder - set stflag to 0, write last address to EEPROM on 18F
End Select
' --------- Interrupt Handler ------------------------------------------------------------
IF PIR1.0 THEN ' IF Timer1 has over-flowed then
Timer = Timer + 1 ' Increment Timer variable
PIR1.0 = 0 ' Clear over-flow/int flag
' @20MHz 200nS * 65,536 * 8 = 0.1048576 seconds per over-flow
' 0.1048576 * 48 = ~5.033 seconds before jump to NextStage
IF Timer >= 48 THEN NextStage
ENDIF
goto Main
return
NextStage: ' Dont really know what you need here. Just a visual test
T1CON.0 = 0 ' Turn off Timer1 if you need to here
Timer = 0 ' Clear Timer var on entry here
TMR1H = 0
TMR1L = 0 ' CLear timer count registers as required
GOTO ReStart ' When you're ready to start all over
' Interrupt handler stuff here
'
Disable ' Disable interrupts in handler
ProcedureSwitcher:
Bmenu = Bmenu + 1 ' Changing tasks only
' I need to be able to do more here... A 'select' button?
If Bmenu = 10 Then Bmenu=1
serout2 ALCDout, LCDbd, [I,CLR]
serout2 ALCDout, LCDbd,[I,L1_C1]
serout2 ALCDout, LCDbd, ["Using Menu #: ",#Bmenu]
pause 500
Here:
While SWITCH = 0 ' waiting until
wend ' push-button is release
pause 100 ' debounce time
If switch = 0 then here
PIR1.0 = 0 ' Clear Timer1 over-flow flag
Timer = 0 ' Clear Timer counts before return
INTCON.1=0 ' reset RB0 interrupt flag
Resume ' Return to main program
Enable ' Enable interrupts after
' handler
The 18F2525 supports multiple interrupts, and even priorities of interupt (which I think I turned off) - EG there is INT on RB0, RB1, RB2... If necessary, I can move the incoming serial data from RB1 to RB5 or so to make space for multiple interrupts.
Anyone have any really good Interrupt/menu experience for such an application? I am sure this is a common type of activity - scroll through menus, then select the one you want, hopefully while something is still happening in the background....
Thanks,
Tom
Bookmarks