OK.. this is a declaration
.. but this set port as input ..
or is the same with alias with
No I don't have proteus.
From what I see you have problems once the first row to move to the second and you are taken to the last, while pressing the select button will change the menu properly. Is there anything on the index of the row that does not convince me. You have created a variable to store the YPos that works for viewing option but maybe has some problems on the slider.
I think that you have used for the buttons a circuit different to the original (buttons on PORTC and not PORTB) and the key is pressed when the buttons are equal at 0. In the source of Andy0 keys are pressed when level is 1.
In your source you have to change the line where test keys not pressed from
Code: Select all
...
ElseIf (PORTB And %01110000) = 0 Then
' all buttons pin are grounded and other pin of PORTB ar masked by AND
Inc (NoButtonCount)
EndIf
...
to this
Code: Select all
...
ElseIf (PORTC And %00000111) = 7 Then
' all buttons pin are at +5V and other pin of PORTC are masked by AND
Inc (NoButtonCount)
EndIf
...
I do not know if this is enough to run everything else but it certainly is wrong.
Surely, the fact to test incorrectly the condition of "not pressed" triggers a series of problems including the resetting of the variables debounce. At the only one push of a "Down" without debouncing the button you are not sure to request only one MoveDown (), and since the lines are only 4, you are at the last option without realizing it.
I'm sorry but I have broken down the original version of the module and I preferred to generalize the procedure by placing the ability to place the menu at will.
Now in your main program can set mnuXPos, mnuYPos, mnuYStep and mnuXCurs with
Code: Select all
Initialise(pItemActionEvent As TEvent,
XMnuPos As Byte = 20,
YMnuPos As Byte = 10,
YMnuStep As Byte = 10,
XMnuCurs As Byte = 10
.. by default menu is draw at x=20,y=10 with line spacing of 10 and the cursor is draw at x=10
The following is a generalization of the module ..
Code: Select all
Module RYMenu
Include "glcd"
#ifdef MenuDataModule
Include MenuDataModule
#else
#error "No MenuDataModule defined in main program"
#endif
#option Menu_LCDLines = 4 'Number of lines on LCD display
#option Menu_ShowMenuTitle = True 'Display Menu Name at top of screen?
#option Menu_ShowScrollIndicators = True 'Show up and down scroll indicators?
#option Menu_ScrollWrapping = False 'Scroll wraps from top to bottom?
#option Menu_PointerCharacter = 126 'Character used as pointer
#if Menu_LCDLines = 1 And Menu_ShowMenuTitle = True
#error "Cannot show menu titles on 1 line LCD"
#endif
Type TEvent = Event()
Private Const
LCDLines As Byte = Menu_LCDLines,
PointerCharacter As Byte = Menu_PointerCharacter
#If Menu_ShowScrollIndicators = True
'Character definitions for Up Arrow and Down Arrow scroll indicators
Private Const ScrollIndicators(16) As Byte=($04,$0E,$1F,$00,$00,$00,$00,$00,
$00,$00,$00,$00,$00,$1F,$0E,$04)
Private Const UpArrow = 0
Private Const DownArrow = 1
#EndIf
Private Dim FItemActionEvent As TEvent 'Holds pointer to event code in main
'program which is run when an "action"
'menu item is selected
Private Dim PointerPosition As Byte 'Position of pointer character (0 = 1st)
Private Dim PointerLine As Byte 'Actual LCD line of pointer
Private Dim ScrollPosition As Byte 'Number of lines the menu is scrolled by
Private Dim CurrentMenu As Byte 'Index number of current menu
Private Dim ParentID As Byte 'Index number of parent of current menu
Private Dim FirstItemNumber As Byte 'First item number for current menu
Private Dim LastItemNumber As Byte 'Last item number for current menu
Public Dim SelectedMenuItem As Byte 'Index number of selected menu item
'===============================================================================
'Name: DrawMenu(pMenuNumber as byte)
'Purpose: Draws current menu, scrolled by ScrollPosition amount
'
Private Dim
xPos As Byte,
yPos As Byte,
yStep As Byte,
xCurs As Byte
Dim LineNumber As Byte 'Line number of LCD to write at
Private Function GetYPos(p As Byte = 0) As Byte
If p<>0 Then
result = (p - 1) * yStep
Else
result = (LineNumber - 1) * yStep
End If
End Function
Private Sub DrawMenu()
Dim ItemNumber As Byte 'Index of menu item number to write
#If Menu_ScrollWrapping = True
Dim ItemsDrawn As Byte
ItemsDrawn = 0
#EndIf
'LCDI2C.Cls
GLCD.Cls(1)
LineNumber = 1
ItemNumber = FirstItemNumber + ScrollPosition
#If Menu_ShowMenuTitle = True
' LCDI2C.WriteConstStringAt(1, 1, mnuMenuName(CurrentMenu))
GLCD.WriteStr(xPos, GetYPos() , mnuMenuName(CurrentMenu))
LineNumber = 2
#Endif
Repeat
'LCDI2C.WriteConstStringAt(LineNumber, 2, mnuItemName(ItemNumber))
GLCD.WriteStr(xPos, GetYPos() , mnuItemName(ItemNumber))
Inc(LineNumber)
Inc(ItemNumber)
#If Menu_ScrollWrapping = True
Inc(ItemsDrawn)
If ItemNumber > LastItemNumber Then
ItemNumber = FirstItemNumber
EndIf
Until LineNumber > LCDLines Or ItemsDrawn > LastItemNumber - FirstItemNumber
#Else
Until LineNumber > LCDLines Or ItemNumber > LastItemNumber
#EndIf
#If Menu_ShowScrollIndicators = True
#If Menu_ScrollWrapping = True
#If Menu_ShowMenuTitle = True
If LastItemNumber - FirstItemNumber > LCDLines - 1 Then
'LCD.WriteAt(LCDLines, 1, DownArrow)
GLCD.WriteAt(xCurs, GetYPos(LCDLines) , DownArrow)
'LCD.WriteAt(2, 1, UpArrow)
GLCD.WriteAt(xCurs, GetYPos(2) , UpArrow)
#Else
If LastItemNumber - FirstItemNumber > LCDLines Then
'LCD.WriteAt(LCDLines, 1, DownArrow)
GLCD.WriteAt(xCurs, GetYPos(LCDLines) , DownArrow)
'LCD.WriteAt(1, 1, UpArrow)
GLCD.WriteAt(xCurs, GetYPos(1) , UpArrow)
#EndIf
EndIf
#Else
If ItemNumber - 1 < LastItemNumber Then
'LCDI2C.WriteAt(LCDLines, 1, DownArrow)
GLCD.WriteAt(xCurs, GetYPos(LCDLines) , DownArrow)
EndIf
If ScrollPosition > 0 Then
#If Menu_ShowMenuTitle = True
'LCDI2C.WriteAt(2, 1, UpArrow)
GLCD.WriteAt(xCurs, GetYPos(2) , UpArrow)
#Else
'LCDI2C.WriteAt(1, 1, UpArrow)
GLCD.WriteAt(xCurs, GetYPos(1) , UpArrow)
#EndIf
EndIf
#EndIf
#EndIf
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Name: DrawPointer(pOldPosition as byte)
'Purpose: Deletes pointer at pOldPosition and draws pointer at PointerPosition
'Notes: When pointer is at first menu item on screen, PointerPosition = 0
' Pointer character determined by option "Menu_PointerCharacter",
' default = 126 (right arrow)
Private Sub DrawPointer(pOldPosition As Byte)
'Actual LCD line which pointer is drawn on depends on whether
'Menu_ShowMenuTitle is enabled or not
#If Menu_ShowMenuTitle Then
PointerLine = PointerPosition + 2
'LCDI2C.WriteAt(pOldPosition + 2, 1, " ")
'LCDI2C.WriteAt(PointerLine, 1, PointerCharacter)
GLCD.WriteAt(xCurs, GetYPos(pOldPosition + 2) , " ")
GLCD.WriteAt(xCurs, GetYPos(PointerLine) , PointerCharacter)
#Else
PointerLine = PointerPosition + 1
'LCDI2C.WriteAt(pOldPosition + 1, 1, " ")
'LCDI2C.WriteAt(PointerLine, 1, PointerCharacter)
GLCD.WriteAt(xCurs, GetYPos(pOldPosition + 1) , " ")
GLCD.WriteAt(xCurs, GetYPos(PointerLine) , PointerCharacter)
#EndIf
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Name: ShowMenu(pMenuNumber as byte = 0)
'Purpose: Display specified menu on LCD
Public Sub ShowMenu(pMenuNumber As Byte = 0)
'Reset scroll and pointer positions
ScrollPosition = 0
PointerPosition = 0
CurrentMenu = pMenuNumber
ParentID = mnuParentMenuID(CurrentMenu)
FirstItemNumber = mnuMenuItemStart(CurrentMenu)
LastItemNumber = mnuMenuItemEnd(CurrentMenu)
DrawMenu
DrawPointer(0)
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Name: MoveDown()
'Purpose: Move pointer to next menu item, scrolling the menu if necessary
Public Sub MoveDown()
Dim CanScroll As Boolean
'First, determine if the menu can be scrolled down and set CanScroll -
'
' If Scroll Wrapping Not Enabled: Menu may only be scrolled down if the
' number of menu items left to display won't fit on the number of
' available LCD lines
'
' Note: Number of available lines depends on whether Menu_ShowMenuTitle is
' enabled or not
'
' If Scroll Wrapping Enabled: Can always scroll down
#If Menu_ScrollWrapping = False
CanScroll = False
#If Menu_ShowMenuTitle = True Then
If FirstItemNumber + ScrollPosition + LCDLines - 2 < LastItemNumber Then
CanScroll = True
EndIf
#Else
If FirstItemNumber + ScrollPosition + LCDLines - 1 < LastItemNumber Then
CanScroll = True
EndIf
#EndIf
#Else
CanScroll = True
#EndIf
'Scroll the menu if the following conditions exist -
'
' Menu can be scrolled down and pointer is on or below the second last
' line of the display
' OR
' Menu can be scrolled down and pointer is on the last menu item - this
' allows scroll wrapping
If (PointerLine >= LCDLines - 1 Or PointerPosition = LastItemNumber - FirstItemNumber) And CanScroll = True Then
Inc(ScrollPosition)
#If Menu_ScrollWrapping = True
'If scroll wrapping and we've scrolled to the bottom then start again at
'the top
If ScrollPosition > (LastItemNumber - FirstItemNumber) Then
ScrollPosition = 0
EndIf
#EndIf
DrawMenu()
DrawPointer(PointerPosition)
'If not scrolling the menu then move the pointer down if the following
'conditions exist -
'
' Pointer is not on the last line of the display
' AND
' Pointer isn't on the last menu item
ElseIf PointerLine < LCDLines And PointerPosition + FirstItemNumber + ScrollPosition < LastItemNumber Then
Inc(PointerPosition)
'Fix to ensure Up Arrow scroll indicator is shown on smaller displays
'when pointer moves down from top line
#If (Menu_LCDLines < 4 Or Menu_ScrollWrapping = True) And Menu_ShowScrollIndicators = True
DrawMenu()
DrawPointer(PointerPosition)
#Else
DrawPointer(PointerPosition - 1)
#EndIf
End If
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Name: MoveUp()
'Purpose: Move pointer to previous menu item, scrolling menu if necessary
Public Sub MoveUp()
'Routine decides whether to scroll the menu up or just move the pointer up
'depending on the current state:
'
'If there is a free LCD line above the pointer (i.e. one that doesn't have
'the menu title or a scroll indicator in it then move the pointer up;
'
'Otherwise, if the menu can be scrolled (either because scroll wrapping is
'on or because the current scroll position > 0) then scroll the menu up;
'
'If the menu can't be scrolled then move the pointer up, overwriting any
'scroll-up indicator. (If necessary, re-draw the scroll-down indicator).
#If Menu_ShowMenuTitle = True
#If Menu_ShowScrollIndicators = True
If PointerLine > 3 Then
#Else
If PointerLine > 2 Then
#EndIf
Dec(PointerPosition)
DrawPointer(PointerPosition + 1)
#If Menu_ScrollWrapping = True
Else
If ScrollPosition > 0 Then
Dec(ScrollPosition)
Else
ScrollPosition = LastItemNumber - FirstItemNumber
EndIf
DrawMenu()
DrawPointer(PointerPosition)
EndIf
#Else
ElseIf ScrollPosition > 0 Then
Dec(ScrollPosition)
DrawMenu()
DrawPointer(PointerPosition)
ElseIf PointerLine > 2 Then
Dec(PointerPosition)
#If Menu_LCDLines < 4 And Menu_ShowScrollIndicators = True
DrawMenu()
DrawPointer(PointerPosition)
#Else
DrawPointer(PointerPosition + 1)
#EndIf
EndIf
#EndIf
#Else
#If Menu_ShowScrollIndicators = True
If PointerLine > 2 Then
#Else
If PointerLine > 1 Then
#EndIf
Dec(PointerPosition)
DrawPointer(PointerPosition + 1)
#If Menu_ScrollWrapping = True
Else
If ScrollPosition > 0 Then
Dec(ScrollPosition)
Else
ScrollPosition = LastItemNumber - FirstItemNumber
EndIf
DrawMenu()
DrawPointer(PointerPosition)
EndIf
#Else
ElseIf ScrollPosition > 0 Then
Dec(ScrollPosition)
DrawMenu()
DrawPointer(PointerPosition)
ElseIf PointerLine > 1 Then
Dec(PointerPosition)
#If Menu_LCDLines < 4 And Menu_ShowScrollIndicators = True
DrawMenu()
DrawPointer(PointerPosition)
#Else
DrawPointer(PointerPosition + 1)
#EndIf
EndIf
#EndIf
#EndIf
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Name: Back()
'Purpose: Show parent of current menu
Public Sub Back()
ShowMenu(ParentID)
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Name: SelectItem()
'Purpose: Carries out action of selected menu item. If menu item opens
' another menu then that menu is drawn. If menu item is an 'action'
' item then the event in the main program which handles the action is
' called
Public Sub SelectItem()
Dim ItemAction As Byte
SelectedMenuItem = FirstItemNumber + ScrollPosition + PointerPosition
#If Menu_ScrollWrapping = True
If SelectedMenuItem > LastItemNumber Then
SelectedMenuItem = SelectedMenuItem - (LastItemNumber - FirstItemNumber) - 1
EndIf
#EndIf
ItemAction = mnuItemAction(SelectedMenuItem)
If ItemAction = 255 Then
ParentID = CurrentMenu 'Means 'back' command will return to correct menu
FItemActionEvent() 'Call event handler in main program
Else
ShowMenu(ItemAction)
EndIf
End Sub
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'Name: Initialise(pItemActionEvent as TEvent)
'Purpose: Sets name of main program event handler and loads custom scroll
' characters into LCD
Public Sub Initialise(pItemActionEvent As TEvent,
XMnuPos As Byte = 20,
YMnuPos As Byte = 10,
YMnuStep As Byte = 10,
XMnuCurs As Byte = 10 )
xPos = XMnuPos
yPos = YMnuPos
yStep = YMnuStep
xCurs = XMnuCurs
FItemActionEvent = pItemActionEvent
' #If Menu_ShowScrollIndicators = True Then
' LCDI2C.Write(ScrollIndicators)
' #EndIf
End Sub