' -----------------------------------------------------------------------
' Pic Clock version 1.0
' Written by Eric James November - 2004
' Updated for Version 1.0Beta10  July - 2007
'
' Display the time on the dsPICDEM V1.1 developement board
' Buttons 1 and 2 adjust the hours
' Buttons 3 and 4 adjust the minutes
'

#include <libs/30f6014.bas>		' register definitions for the 30F6014 processor
#include "dsPicDEM.bas"			' routines to use with picDEM1.1 board
#include "strings.bas"			' misc string routines

Dim hours,minutes,seconds As uInteger	' Time keeping variables

Dim button1 @ porta.12 As Boolean	' setup an alias to each button so the code will be
Dim button2 @ porta.13 As Boolean	' easier to read
Dim button3 @ porta.14 As Boolean
Dim button4 @ porta.15 As Boolean


Dim updFlg As Boolean						' Interrupt routine set's this flag when it is time to update the display

Sub main()							' The program starts here at Sub main()
	init()							' initialize variables
	While true						' endless loop
		buttonWatcher()					' watch for a button press
		handelButtonPress()				' Handel a button press
		If updFlg=1 Then updateDisplay(): updFlg=0	' update the display when needed
	End While

End Sub



Sub init()

 	lcd_Init()			' initialize the LED display
	hours=0: minutes=0: seconds=0	' clear the time
	updFlg = 1			' signal to update the display
	
	btn1State=0: btn2State=0	' initialize the button state machines
	btn3State=0: btn4State=0
	button1Pressed=0
	button2Pressed=0
	button3Pressed=0
	button4Pressed=0
	
	TRISA=0xFFFF			' make sure port a is an input
	
	' ------------------------------- Setup the timer
	' Timer 1 is used for keeping track of the time
	T1CON = 0x8030
	PR1=28801
	T1IE=1			' Turn on T1 Interrupt
	
	
	' ------------------------------- Setup timer 2
	' Timer2 is used as a debounce timer for the switches
	T2CON = 0x8000		' Setup T2 for 1mS timeout
	PR2=7373
	T2IE=1				' turn on Timer2 interrupts
	
End Sub


Sub updateDisplay()
	Dim s(30) As String

	lcd_homeclear()					' clear the LCD
	lcd_puts("Time:")				' Display message
	lcd_pos(0,1)
	
	ui2a(hours,s):LPad(s,"0",2): lcd_puts(s)	' Display the time
	lcd_putc(":")
	ui2a(minutes,s):LPad(s,"0",2): lcd_puts(s)
	lcd_putc(":")
	ui2a(seconds,s):LPad(s,"0",2): lcd_puts(s)
End Sub

Sub timeKeeper() T1Interrupt
	T1IF=0					' IMPORTANT! Reset the interrupt flag
	
	seconds +=1
	If seconds>59 Then
		seconds = 0
		minutes +=1
		If minutes>59 Then
			minutes=0
			hours +=1
			If hours>12 Then hours=1
		End If
	End If
	
	updFlg=1				' signal to refresh the display
End Sub

Sub buttonTimeKeeper() T2Interrupt
	T2IF=0			' reset the interrupt flag
	btn1Timer +=1		' this happens every 1mS
	btn2Timer +=1
	btn3Timer +=1
	btn4Timer +=1
End Sub

Dim btn1State,btn2State,btn3State,btn4State As uInteger		' keep track of the states the buttons are in
Dim btn1Timer,btn2Timer,btn3Timer,btn4Timer As uInteger		' time keeping for button debouncing

Dim button1Pressed,button2Pressed As Boolean			' 1 when the button has been pressed and released
Dim button3Pressed,button4Pressed As Boolean

Const btn_waitingOnPress = 0					' states
Const btn_waitingOnRelease = 1

Const debounceTime = 50						' debounce time in milli seconds

Sub buttonWatcher()
		
	Select Case btn1State ' ---------------------------------------- Monitor button 1
		Case btn_waitingOnPress
			If button1=0 Then				' has this button been pressed ?
				If btn1Timer>debounceTime Then		' Yes, has the timer expired ?
					btn1State=btn_waitingOnRelease	' Yes, so advance to the next state
					btn1Timer = 0			' 	and zero the timer
				End If
			Else						' No, the button has not been pressed
				btn1Timer=0				'	so zero the debounce timer
			End If
			
			
		Case btn_waitingOnRelease
			If button1=1 Then				' has the button been released ?
				If btn1Timer>debounceTime Then		' Yes, has the timer expired ?
					btn1State=btn_waitingOnPress	' Yes so return back to the previous state
					btn1Timer=0			'	and zero the timer
					button1Pressed=1		'	and mark the button as being pressed and released
				End If
			Else						' No, the button has not been released
				btn1Timer=0				'	so zero the debounce timer
			End If
			
		Case Else: btn1State=0					' Invalid state so jump to waiting on a button press
	End Select


	Select Case btn2State ' ---------------------------------------- Monitor button 2
		Case btn_waitingOnPress
			If button2=0 Then				' has this button been pressed ?
				If btn2Timer>debounceTime Then		' Yes, has the timer expired ?
					btn2State=btn_waitingOnRelease	' Yes, so advance to the next state
					btn2Timer = 0			' 	and zero the timer
				End If
			Else						' No, the button has not been pressed
				btn2Timer=0				'	so zero the debounce timer
			End If
			
			
		Case btn_waitingOnRelease
			If button2=1 Then				' has the button been released ?
				If btn2Timer>debounceTime Then		' Yes, has the timer expired ?
					btn2State=btn_waitingOnPress	' Yes so return back to the previous state
					btn2Timer=0			'	and zero the timer
					button2Pressed=1		'	and mark the button as being pressed and released
				End If
			Else						' No, the button has not been released
				btn2Timer=0				'	so zero the debounce timer
			End If
			
		Case Else: btn2State=0					' Invalid state so jump to waiting on a button press
	End Select


	Select Case btn3State ' ---------------------------------------- Monitor button 3
		Case btn_waitingOnPress
			If button3=0 Then				' has this button been pressed ?
				If btn3Timer>debounceTime Then		' Yes, has the timer expired ?
					btn3State=btn_waitingOnRelease	' Yes, so advance to the next state
					btn3Timer = 0			' 	and zero the timer
				End If
			Else						' No, the button has not been pressed
				btn3Timer=0				'	so zero the debounce timer
			End If
			
			
		Case btn_waitingOnRelease
			If button3=1 Then				' has the button been released ?
				If btn3Timer>debounceTime Then		' Yes, has the timer expired ?
					btn3State=btn_waitingOnPress	' Yes so return back to the previous state
					btn3Timer=0			'	and zero the timer
					button3Pressed=1		'	and mark the button as being pressed and released
				End If
			Else						' No, the button has not been released
				btn3Timer=0				'	so zero the debounce timer
			End If
			
		Case Else: btn3State=0					' Invalid state so jump to waiting on a button press
	End Select
	
	Select Case btn4State ' ---------------------------------------- Monitor button 4
		Case btn_waitingOnPress
			If button4=0 Then				' has this button been pressed ?
				If btn4Timer>debounceTime Then		' Yes, has the timer expired ?
					btn4State=btn_waitingOnRelease	' Yes, so advance to the next state
					btn4Timer = 0			' 	and zero the timer
				End If
			Else						' No, the button has not been pressed
				btn4Timer=0				'	so zero the debounce timer
			End If
			
			
		Case btn_waitingOnRelease
			If button4=1 Then				' has the button been released ?
				If btn4Timer>debounceTime Then		' Yes, has the timer expired ?
					btn4State=btn_waitingOnPress	' Yes so return back to the previous state
					btn4Timer=0			'	and zero the timer
					button4Pressed=1		'	and mark the button as being pressed and released
				End If
			Else						' No, the button has not been released
				btn4Timer=0				'	so zero the debounce timer
			End If
			
		Case Else: btn4State=0					' Invalid state so jump to waiting on a button press
	End Select
	

End Sub

Sub handelButtonPress()
	' Watch for a button to be pressed and react accordingly
	
	If button1Pressed=1 Then			' has button 1 been pressed ?
		button1Pressed=0			'	Yes so clear the flag
		hours +=1				'	inc the hours
		If hours>23 Then hours=0		' 	handel an overflow		
		updFlg=1				' 	set the update display flag
	End If
	
	If button2Pressed=1 Then			' has button 2 been pressed ?
		button2Pressed=0			'	Yes so clear the flag
		hours = hours-1				'	dec the hours
		If hours>23 Then hours = 23		' 	handel an underflow
		updFlg=1				'	set the update display flag
	End If
	
	If button3Pressed=1 Then			' has button 3 been pressed ?
		button3Pressed=0			'	Yes so clear the flag
		minutes +=1				'	inc the minutes
		If minutes>59 Then hours=0		' 	handel an overflow		
		updFlg=1				' 	set the update display flag
	End If
	
	If button4Pressed=1 Then			' has button 4 been pressed ?
		button4Pressed=0			'	Yes so clear the flag
		minutes = minutes-1			'	dec the minutes
		If minutes>59 Then hours = 59		' 	handel an underflow
		updFlg=1				'	set the update display flag
	End If

End Sub