Picaxe Digital Guitar Clock

JSDL

Senior Member
The Picaxe LED Guitar clock is based on a Picaxe 20M2 microcontroller and DS3231 Real Time Clock chip. It reads the time stored in the RTC and display it on a 7 segment display made up of individual LEDs. The project makes use of 6 74HC595 serial to parallel shift registers to save on I/O pins, one for each 7 segment digit. The entire circuit is housed inside an acoustic guitar casing. It has 3 push button switches, one to enter time set mode, and the other two for incrementing, decrementing the hours/minutes/seconds. The clock also has an AM/PM LED indicator.

Code:
init:  pause 500
setfreq m32

i2cslave %11010000, i2cslow, i2cbyte	 'Set slave address for DS3231 module
pause 40

'#########Create symbols for 74HC595 Data, Clock and Latch pins

symbol sclk=c.1
symbol latch=c.3
symbol sdata=c.2

'#########Initialize Variables

symbol bitcounter = b1
symbol outbit = b2
symbol outbyte = b3
symbol counter = b4


symbol seconds = b5
symbol mins = b6
symbol hour = b7
symbol hour12=b8
symbol ampm_bit=b9


symbol digout = b10
symbol bcdmin=b11
symbol bcdmax=b12
symbol bcdnum=b13
symbol work=b20
symbol timesetledflash=b21
symbol temp=b22

'#######Create symbols for time setting buttons

symbol setbutton=pinc.0
symbol incbutton=pinb.4
symbol decbutton=pinb.3
symbol up=0
symbol down=1


'##########Set MR LOW and OE HIGH on 74HC595 Shift Register

symbol MR=c.5
symbol OE=c.4

high MR
low OE

'#############Ensure Data CLK, Data-In and Latch pins are initially low

low sclk
low sdata
low latch

'#############Main Loop

MAIN:

do 
	if setbutton=down then
	gosub settime
	else
	gosub displaytime
	endif
loop


SETTIME:

high c.7 	'###########Time Set LED indicator

for timesetledflash = 1 to 5
	high c.4
	high b.2
	pause 1000
	low c.4
	low b.2
	pause 1000
next timesetledflash


do while setbutton=down loop

readi2c 0,(seconds,mins,hour)
gosub displaytime

gosub sethour
gosub setmins
gosub setseconds
gosub setampm
low c.7

do while setbutton=down loop
return


'############Subprocedure for setting the hour
SETHOUR:

do while setbutton=down loop

bcdmax=$12:bcdmin=$01

do


if incbutton=down then
	bcdnum=hour & $1F
	gosub bcdinc	
	temp = hour & $20
	
	if temp = 32 then
		hour=bcdnum | %01100000
		else
		hour=bcdnum | %01000000
	endif	
	
	writei2c 2,(hour)	
do while incbutton=down loop
endif

if decbutton=down then
	bcdnum=hour & $1F
	gosub bcddec	
	temp = hour & $20
	
	if temp = 32 then
		hour=bcdnum | %01100000
		else
		hour=bcdnum | %01000000
	endif	
	
	writei2c 2,(hour)
do while decbutton=down loop
endif

gosub displaytime
if setbutton=down then exit
loop

return

'############Subprocedure for setting the minutes
SETMINS:

do while setbutton=down loop

bcdmax=$59:bcdmin=$00

do


if incbutton=down then
	bcdnum=mins
	gosub bcdinc
	mins=bcdnum
	writei2c 1, (mins)	
do while incbutton=down loop
endif

if decbutton=down then
	bcdnum=mins
	gosub bcddec
	mins=bcdnum
	writei2c 1, (mins)
do while decbutton=down loop
endif

gosub displaytime
if setbutton=down then exit
loop

return


'############Subprocedure for setting the seconds
SETSECONDS:

do while setbutton=down loop

bcdmax=$59:bcdmin=$00

do


if incbutton=down then
	bcdnum=seconds
	gosub bcdinc
	seconds=bcdnum
	writei2c 0,(seconds)	
do while incbutton=down loop
endif

if decbutton=down then
	bcdnum=seconds
	gosub bcddec
	seconds=bcdnum
	writei2c 0, (seconds)
do while decbutton=down loop
endif

gosub displaytime
if setbutton=down then exit
loop

return

'############Subprocedure for setting AM/PM
SETAMPM:

do while setbutton=down loop

bcdmax=$01:bcdmin=$00

do


if incbutton=down then
	bcdnum=hour & $20 /32
	gosub bcdinc
	bcdnum=bcdnum * 32
	hour=hour & $DF | bcdnum
	hour=hour | %01000000
	writei2c 2,(hour)
	do while incbutton=down loop
endif

if decbutton=down then
	bcdnum=hour & $20 /32
	gosub bcdinc
	bcdnum=bcdnum * 32
	hour=hour & $DF | bcdnum
	hour=hour | %01000000
	writei2c 2,(hour)
	do while decbutton=down loop
endif


gosub displaytime
if setbutton=down then exit
loop

return

'############Subprocedure for incrementing values in Time Set mode
BCDINC:

bcdnum=bcdnum+1
work=bcdnum & $0F
	if work=10 then
	bcdnum=bcdnum+6
	endif

	if bcdnum > bcdmax then
	bcdnum=bcdmin
	endif
return

'############Subprocedure for decrementing values in Time Set mode
BCDDEC:

if bcdnum=bcdmin then
bcdnum=bcdmax
else
bcdnum=bcdnum -1
work = bcdnum & $0F
	if work >= $0F then
	bcdnum=bcdnum - 6
	endif
endif

return


'############Output time to 7 Segment displays

DISPLAYTIME:

readi2c 0,(seconds, mins, hour)

gosub CONVERT_TO_12HOUR
gosub CHECK_AM_PM

'###########Convert BCD values to ASCII

bcdtoascii seconds,b14,b15	'SECONDS
bcdtoascii mins,b16,b17		'MINS
bcdtoascii hour12,b18,b19	'HOURS

'###########Convert ASCII values to Characters

b14=b14 - $30	
b15=b15 - $30
b16=b16 - $30	
b17=b17 - $30	
b18=b18 - $30	
b19=b19 - $30	

'############Pass decimal digit values to Shift Subroutine

digout = b15		
gosub shift595

digout = b14
gosub shift595

digout = b17
gosub shift595

digout = b16
gosub shift595

digout = b19
gosub shift595

digout = b18
gosub shift595

	pulsout latch,4
	return
	
'#########Subroutine to push data bits to shift registers

shift595:

lookup digout, ($FC,$60,$DA,$F2,$66,$B6,$BE,$E0,$FE,$E6), outbyte	'Lookup digits and convert to byte patterns for output to 7 segment displays

for bitcounter = 0 to 7
	outbit = outbyte & 128

	if outbit = 128 then 
		high sdata
		else
		low sdata
	endif
	
	pulsout sclk, 1
	outbyte=outbyte * 2
next bitcounter

return


'Subprocedure to extract 12 Hour time and check for single/double digits
CONVERT_TO_12HOUR:

hour12 = b7 and $1F	'Extract 12 hour time from hour byte
if hour12 < 10 then
	pause 200
	high b.2
	else
	low b.2
endif
return

'############Subprocedure for setting AM/PM LED
CHECK_AM_PM:

	ampm_bit=b7 and $20	'Extract AM/PM bit from hour byte
	if ampm_bit=32 then	'Test AM/PM bit and turn on associated LED
	low b.1
	else	
	high b.1
	endif
return
View attachment 18222View attachment 18223
 
Top