MenuCode
MenuCode
DEFINE OSC 48 ' Loader configured for 20MHz OSC on USB board
DEFINE RESET_ORG 0x1000 ' User code start location for HID loader
'******************************************************************************
'* SET UP LCD DISPLAY FOR PROJECT BOARD
'* Refer to manual for description of defines
'* Your logic will need to be modified to match your circuit
'******************************************************************************
' Set LCD Data port
DEFINE LCD_DREG PORTD
' Set starting Data bit (0 or 4) if 4-bit bus
DEFINE LCD_DBIT 4
' Set LCD Register Select port
DEFINE LCD_RSREG PORTD
' Set LCD Register Select bit
DEFINE LCD_RSBIT 2
' Set LCD Enable port
DEFINE LCD_EREG PORTD
' Set LCD Enable bit
DEFINE LCD_EBIT 3
' Set LCD bus size (4 or 8 bits)
DEFINE LCD_BITS 4
' Set number of lines on LCD
DEFINE LCD_LINES 2
' Set command delay time in us
DEFINE LCD_COMMANDUS 2000
' Set data delay time in us
DEFINE LCD_DATAUS 50
'******************************************************************************
'* Setup DT_INTS INCLUDES
'******************************************************************************
INCLUDE "DT_INTS-18.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ' Include if using PBP interrupts
'******************************************************************************
'* Configure inputs for menu buttons
'******************************************************************************
INPUT PORTB.2
INPUT PORTB.3
INPUT PORTB.4
INPUT PORTB.5
INPUT PORTB.7
'******************************************************************************
'Solenoid Outputs
output PORTA.4
output PORTA.5
OUTPUT PORTB.1
OUTPUT PORTE.0
OUTPUT PORTE.1
OUTPUT PORTE.2
'******************************************************************************
'* Configure Constants for Menus
'* Spacing is left between some of the menu CON to allow for
'* future menus.
'******************************************************************************
mnuMAIN con 0 'Top Most Menu
mnuMENU_A con 10
mnuMENU_A_1 Con 11
mnuMENU_A_2 CON 12
mnuMENU_B CON 20
mnuMENU_B_1 con 21
mnuMENU_B_1A con 22
mnuMENU_B_1B con 23
mnuMENU_B_2 con 25
mnuMENU_B_2A con 26
mnuMENU_C CON 30
mnuMENU_C_1 con 31
mnuMENU_C_2 con 32
mnuMENU_C_3 con 33
mnuMENU_C_3A con 34
mnuMENU_C_3B con 35
mnuMENU_C_4 con 36
mnuMENU_D con 40
mnuMENU_D_1 Con 41
mnuMENU_D_2 CON 42
'And one variable in the constants section to store the value of the menu
MainMenu VAR BYTE
'******************************************************************************
'* Configure Variables for Buttons
'* In this example, all buttons are on PORT B
'******************************************************************************
pbMenuPort var PORTB
pbMask Con $BC 'Mask is used to filter out other I/O on PortB
pbTemp var byte 'Storage for confirming masked button inputs
pbTemp2 var byte 'Starate for confirming masked button inputs
'******************************************************************************
'* Configure Variables for LED
'* All projects need at least one LED :-)
'******************************************************************************
LED1 VAR PORTB.6
'******************************************************************************
'* Configure Variables for program
'******************************************************************************
Loops VAR BYTE
x var byte
y var byte
z var byte
StartDecOfX var bit
Timer100ms var byte :Timer100ms = 4
Timer500ms var byte :Timer500ms = 5
'******************************************************************************
'* Hardware configuration
'******************************************************************************
ADCON1 = %00001111 ' All Digital
INTCON2.7 = 0 ; Enable Pull up resistors on Port B
'******************************************************************************
'* Configure timer1 interrupt
'******************************************************************************
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler TMR1_INT, _MainTimerInt, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
'******************************************************************************
'* Start of Program
'******************************************************************************
Main:
pause 2500 'let LCD warm up
LCDOUT $FE, 1, "Welcome" ' Clear display and show message
pause 2000
lcdout $FE, 1 ' Clear display
'Add other startup logic here
'May need to read saved data from EEPROM
'Set state of outputs to known values
'Read some sensor inputs to decide what menu to start on
'etc...
'******************************************************************************
'* All heavy lifting, "processing of main logic", occurs in this section
'* or branches out and back into this section.
'******************************************************************************
Menu_Program:
'can have up to 255 menus, since MainMenu is defined as a BYTE
select case MainMenu
'button is still on...will just keep flying through menus...
case 0
lcdout $FE, $80, "Main Menu" 'Start at beginning of 1st line
gosub Buttons_Off
gosub Scan_Buttons
'**********************************************************************
'**** MENU_A
'**********************************************************************
'as an example this code will decrement x every 100 milliseconds
'after the enter pb has been pressed
'then goto sub menu 2 and decrement y until y=0
case mnumenu_a
lcdout $FE, $80, "Press Enter to Start"
gosub buttons_off
gosub scan_buttons
if pbenter = pressed then
StartDecOfX = 1
buttonflag = 0
mainmenu = mnumenu_a_1
lcdout $FE, 1
endif
if pbmenu = pressed then
startdecofx = 0
buttonflag = 0
mainmenu = mnuMain
lcdout $FE, 1
endif
case mnumenu_a_1
lcdout $FE, $80, "x = ",_
dec x dig 2,_
dec x dig 1,".",_
dec x dig 0
lcdout $FE, $C0, "y = ",_
dec y dig 2,_
dec y dig 1,".",_
dec y dig 0
gosub buttons_off
gosub scan_buttons
if x = 0 then
lcdout $FE, 1
mainmenu = mnumenu_a_2
endif
if pbmenu = pressed then
lcdout $FE, 1
startdecofx = 0
buttonflag = 0
mainmenu = mnuMain
endif
case mnumenu_a_2
LCDout $FE, $80, "z="
select case z
case 0
LCDout $FE, $82, "Nothing "
case 1
LCDout $FE, $82, "Option 1 "
case 2
LCDout $FE, $82, "Opt 2 "
case 3
LCDout $FE, $82, "Last Option"
end select
gosub buttons_off
gosub scan_buttons
if y = 0 then
lcdout $FE, 1, "Done - Going to"
lcdout $FE, $C0, "Main in 2sec."
pause 2000
mainmenu = mnumain
buttonflag = 0
startdecofx = 0
lcdout $FE, 1
endif
if pbmenu = pressed then
lcdout $FE, 1
startdecofx = 0
buttonflag = 0
mainmenu = mnuMain
endif
'**********************************************************************
'**** MENU_B
'**********************************************************************
case mnumenu_b
lcdout $FE, 2, "Menu B"
gosub Buttons_Off
gosub Scan_buttons
if pbplus = pressed then
MainMenu = mnumenu_c
buttonflag = 0
lcdout $FE, 1
endif
if pbminus = pressed then
MainMenu = mnumenu_D
buttonflag = 0
lcdout $FE, 1
endif
if pbenter = pressed then
MainMenu = mnumenu_b_1
buttonflag = 0
lcdout $FE, 1
endif
if pbMenu = pressed then
mainmenu = mnumain
buttonflag = 0
lcdout $FE, 1
endif
case mnumenu_b_1
lcdout $FE, $80, "Menu B Sub 1"
LCDout $FE, $C0, "2nd Line Sub 1"
gosub buttons_off
gosub scan_buttons
case mnumenu_b_1a
lcdout $FE, $80, "Menu B Sub 1A"
LCDout $FE, $C0, "2nd Line x=",_
dec x dig 2,_
dec x dig 1,".",_
dec x dig 0
gosub buttons_off
gosub scan_buttons
case mnumenu_b_1B
lcdout $FE, $80, "Menu B Sub 1B"
LCDout $FE, $C0, "x is set to ",_
dec x dig 2,_
dec x dig 1,".",_
dec x dig 0
gosub buttons_off
gosub scan_buttons
case mnumenu_b_2
lcdout $FE, $80, "Menu B Sub 2"
LCDout $FE, $C0, "Sub 2, 2nd Line"
gosub buttons_off
gosub scan_buttons
case mnumenu_b_2a
lcdout $FE, $80, "Menu B Sub 2A"
LCDout $FE, $C0, "At the bottom"
gosub buttons_off
gosub scan_buttons
'**********************************************************************
'**** MENU_C
'**********************************************************************
case mnumenu_C
lcdout $FE, 2, "Menu C"
gosub Buttons_Off
gosub Scan_buttons
if pbplus = pressed then
MainMenu = mnumenu_D
buttonflag = 0
lcdout $FE, 1
endif
if pbminus = pressed then
MainMenu = mnumenu_B
buttonflag = 0
lcdout $FE, 1
endif
if pbenter = pressed then
MainMenu = mnumenu_C_1
buttonflag = 0
lcdout $FE, 1
endif
if pbMenu = pressed then
mainmenu = mnumain
buttonflag = 0
lcdout $FE, 1
endif
case mnumenu_C_1
lcdout $FE, $80, "Menu C Sub 1"
LCDout $FE, $C0, "Put choices here"
gosub buttons_off
gosub scan_buttons
case mnumenu_C_2
lcdout $FE, $80, "Menu C Sub 2"
LCDout $FE, $C0, "Hello World"
gosub buttons_off
gosub scan_buttons
case mnumenu_C_3a
lcdout $FE, $80, "Menu C Sub 3 A"
LCDout $FE, $C0, "2nd Line 3A"
gosub buttons_off
gosub scan_buttons
case mnumenu_C_3b
lcdout $FE, $80, "Menu C Sub 3 B"
LCDout $FE, $C0, "3B sub Menu"
gosub buttons_off
gosub scan_buttons
case mnumenu_c_4
lcdout $FE, $80, "Menu C Sub 4"
LCDout $FE, $C0, "y is set to ",_
dec y dig 2,_
dec y dig 1,".",_
dec y dig 0
gosub buttons_off
gosub scan_buttons
'**********************************************************************
'**** MENU_D
'**********************************************************************
case mnumenu_d
lcdout $FE, $80, "Menu D"
LCDout $FE, $C0, "2nd Line of D"
gosub buttons_off
gosub scan_buttons
case mnumenu_D_1
lcdout $FE, $80, "Menu D Sub 1"
'notice the use of padded 'spaces' to overwrite
'longer menus
select case z
case 0
LCDout $FE, $C0, "Nothing "
case 1
LCDout $FE, $C0, "Option 1 "
case 2
LCDout $FE, $C0, "Opt 2 "
case 3
LCDout $FE, $C0, "Last Option"
end select
gosub buttons_off
gosub scan_buttons
case mnumenu_d_2
lcdout $FE, $80, "Menu D sub 2"
LCDout $FE, $C0, "z="
select case z
case 0
LCDout $FE, $C2, "Nothing "
case 1
LCDout $FE, $C2, "Option 1 "
case 2
LCDout $FE, $C2, "Opt 2 "
case 3
LCDout $FE, $C2, "Last Option"
end select
gosub buttons_off
gosub scan_buttons
case else
lcdout $FE, 1, "Invalid Menu"
LCDOUT $FE, $C0, "Menu # = ", dec mainmenu
gosub Buttons_Off
gosub Scan_buttons
if pbmenu = pressed then
mainmenu = 0
buttonflag = 0
endif
end select
'******************************************************************************
'* OTHER_CODE
'* This routine would be the main part of the code that would use
'* information from the configuration menus to do something.
'* Maybe show temperature data, communicate with another device,
'* manipulate a machine, etc.
'******************************************************************************
Other_Code:
'as an example this code will decrement x every 100 milliseconds
'after the enter pb has been pressed
'then goto sub menu 2 and decrement y until y=0
lcdout $FE, $80, "Press Enter to Start"
gosub buttons_off
gosub scan_buttons
if pbenter = pressed then
StartDecOfX = 1
endif
if pbmenu = pressed then
lcdout $FE, 1
startdecofx = 0
mainmenu = 0
endif
return
'*** END OTHER_CODE ***********************************************************
'******************************************************************************
'* SCAN_BUTTONS
'* This routine will read the menu buttons from the PIC port.
'* A mask is used to find the button status since this project has other
'* I/O mixed in on the same port.
'* A debounce is used and then the menu port is read and masked again
'* to verify if a button was really pressed.
'*
'******************************************************************************
Scan_Buttons:
'Buttons are pulled high when not pressed
'normal port b: 1x11 11xx
'need to mask x bits with &BC
'copy port b to temp register and mask off non switch bits
'xor
'a b r
'0 0 0
'1 0 1
'0 1 1
'1 1 0
'XOR the temp variable to determine if anything changed from the first scan
pbTemp = pbTemp xor pbTemp2
'Now check the XOR'd mask to see what stayed the same
'and set the menubutton variable equal to the value on the PORT.
'DONT USE ANY OF THE TEMP BITS TO STORE THE MENU BUTTON STATE, USE
'THE ACTUAL PORT VALUE
if pbtemp.0(pbMenuBit) = 0 then
pbMenu = pbMenuPort.0(pbMenuBit)
endif
if pbtemp.0(pbEnterBit) = 0 then
pbEnter = pbMenuPort.0(pbEnterBit)
endif
if pbtemp.0(pbMinusBit) = 0 then
pbMinus = pbMenuPort.0(pbMinusBit)
endif
if pbtemp.0(pbPlusBit) = 0 then
pbplus = pbMenuPort.0(pbPlusBit)
endif
if pbtemp.0(pbArmBit) = 0 then
pbarm = pbMenuPort.0(pbArmBit)
endif
Return
'*** END SCAN_BUTTONS *********************************************************
'******************************************************************************
'* BUTTONS_OFF
'* Check the ButtonFlag to see if the code should check the state of the
'* menu buttons.
'* If the flag is off then scan the buttons until all buttons are off.
'* If a button is determined to be pressed then this routine will continue
'* to scan the buttons until all menu buttons are NOT PRESSED.
'* Once all the buttons are determined to NOT be pressed then set the
'* ButtonFlag so the code will not scan the buttons again until after a new
'* menu is selected.
'******************************************************************************
Buttons_Off:
'Scan buttons, if nothing pressed then return
'otherwise stay in this routine until button
'is released
if buttonflag = 0 then
repeat
ButtonPressed = 0
gosub scan_buttons
if pbenter = pressed then
ButtonPressed = 1
endif
if pbmenu = pressed then
ButtonPressed = 1
endif
if pbplus = pressed then
ButtonPressed = 1
endif
if pbminus = pressed then
ButtonPressed = 1
endif
if pbarm = pressed then
ButtonPressed = 1
endif
until ButtonPressed = 0
buttonflag = 1 'don't come back till another menu button pressed
endif
return
'*** END BUTTONS_OFF **********************************************************
'******************************************************************************
'* ---[TMR1 - interrupt handler]-----------------------------------------------
'* This timer routine will trigger ever 25ms
'* Counters are used to run code at 100ms and 500ms intervals
'* Every 100ms (0.1s) a flag is set to indicate the code should
'* service something, your code will vary
'* Every 500ms (0.5s) the LED will be toggled
'******************************************************************************
MainTimerInt:
'25ms timer
Timer100ms = Timer100ms - 1
'check if 4 passes have expired
if Timer100ms = 0 then
' Check flags for example code and decrement per flag
if (startdecofx = 1) and (x<>0) then
x = x -1
endif
if (startdecofx = 1) and (x=0) and (y<>0) then
y=y-1
endif
' reload counter with 4
Timer100ms = 4
Timer500ms = Timer500ms - 1
' check if 5 passes have expired
If Timer500ms = 0 then
' toggle led
toggle LED1
' reload counter (5)
Timer500ms = 5
endif
endif
@ INT_RETURN
'*** END MAINTIMERINT *********************************************************
END