;=======================================================================
; tm1638cc.s
- s'AVR version by EH
;
; s'AVR
version tested using LED&KEY board
;
; Examples to
be used with the tm1638 library
; written by Ralf
Jardon (cosmicos@gmx.net), May-July 2017
;
; Comments
related to the datasheet refer to version 1.3 (EN)
;
; License:
GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007
;
; 24-AUG-2017
V1.0 includes support for up to 8 key buttons and a realtime clock
; 27-AUG-2017
V1.1 demo now including a 8*100 hrs elapsed timer
; 05-SEP-2017
V1.2 Elapsed time allows split time to calculate the correction
; various PRINT time routines
moved from .INC to main programm
;=======================================================================
;.NOLIST
.INCLUDE
"tm1638cc_EH.def" ; various
definitions, originally tm1638cc.h
.INCLUDE
"tm1638cc.mac" ; TM1638
macros for the SPI interface
.LIST
.LISTMAC
.CSEG
.ORG $0000 ; Start of program code after Reset
; Reset and
Interrupt Vectors (two address locations each!):
; ATmega328P
can use absolute JMP instructions instead of RJMP!!!
; Otherwise a
NOP is required after RJMP (or after RETI).
rjmp init ; 1
RESET External Pin, Power-on Reset,
nop ; Brown-out Reset and Watchdog System Reset
reti ; 2 INT0addr INT0
External Interrupt Request 0
nop
reti ; 3 INT1addr INT1
External Interrupt Request 1
nop
reti ; 4 PCI0addr PCINT0
Pin Change Interrupt Request 0
nop
reti ; 5 PCI1addr PCINT1
Pin Change Interrupt Request 1
nop
reti ; 6 PCI2addr PCINT2
Pin Change Interrupt Request 2
nop
reti ; 7 WDTaddr WDT Watchdog Time-out Interrupt
nop
reti ; 8 OC2Aaddr TIMER2
COMPA Timer/Counter2 Compare Match A
nop
reti ; 9 OC2Baddr TIMER2
COMPB Timer/Counter2 Compare Match B
nop
reti ; 10 OVF2addr TIMER2 OVF Timer/Counter2 Overflow
nop
reti ; 11 ICP1addr TIMER1 CAPT Timer/Counter1 Capture Event
nop
rjmp time10ms ; 12 OC1Aaddr TIMER1 COMPA Timer/Counter1 Compare Match A
nop ; separate interrupt for 10ms timer
reti ; 13 OC1Baddr TIMER1 COMPB Timer/Counter1 Compare Match B
nop
reti ; 14 OVF1addr TIMER1 OVF Timer/Counter1 Overflow
nop
reti ; 15 OC0Aaddr TIMER0 COMPA Timer/Counter0 Compare Match A
nop
reti ; 16 OC0Baddr TIMER0 COMPB Timer/Counter0 Compare Match B
nop
reti ; 17 OVF0addr TIMER0 OVF Timer/Counter0 Overflow
nop
reti ; 18 SPIaddr SPI, STC SPI Serial Transfer Complete
nop
reti ; 19 URXCaddr USART, RX USART Rx Complete
nop
reti ; 20 UDREaddr USART, UDRE USART, Data Register Empty
nop
reti ; 21 UTXCaddr USART, TX USART, Tx Complete
nop
reti ; 22 ADCCaddr ADC ADC
Conversion Complete
nop
reti ; 23 ERDYaddr EE READY EEPROM Ready
nop
reti ; 24 ACIaddr ANALOG COMP Analog Comparator
nop
reti ; 25 TWIaddr TWI (I2C) 2-wire Serial Interface
nop
reti ; 26 SPMRaddr SPM READY Store Program Memory Ready
nop
;=======================================================================
; INIT and MAIN LOOP
;=======================================================================
.ORG $100 ; alternately
.ORG INT_VECTORS_SIZE
init:
ldi AKKU,
HIGH(RAMEND) ; Initialize
stack pointer
out SPH,
AKKU
ldi AKKU,
LOW(RAMEND)
out SPL,
AKKU
rcall TM1638_INIT
; Initialize Ports, SPI
& TM1638
cli ; prepare
Timer1 interrupts (100 Hz, 10ms)
ldi AKKU,
(1<<WGM12) | (1<<CS11) | (1<<CS10) ; CTC OCR1A, /64
sts TCCR1B,
AKKU ; works with most
standard xtal frequencies
; OCR1A will trigger the 100Hz/10ms timer
and reset the CTC
ldi AKKU,
HIGH(XTAL/6400-1) ; Compare
register A high byte
sts OCR1AH,
AKKU
ldi AKKU,
LOW(XTAL/6400-1) ; Compare
register A low byte
sts OCR1AL,
AKKU
ldi AKKU,
(1<<OCIE1A) ; only 10ms
interrupt
sts TIMSK1,
AKKU ; Enable Timer1 Compare A
clr BUTTONS ; mark pushed key buttons bitwise (up to
8)
ldi yl,low(clk10ms) ; begin of
clock timer values ...
ldi yh,high(clk10ms) ; ...
10ms/sec/min/hrs in SRAM
clr AKKU
FOR COUNT := #20 ; clock time, elapsed time, split time ...
st y+,AKKU ; clear time
locations in SRAM
ENDF
sei ; enable
Interrupts
ldi AKKU,1
mov TRUE,AKKU ; register
TRUE stays always 1
ldi AKKU3,
1 ;
"88888888", Text block 1
rcall TM1638_PRINT_TXT8
rcall TM1638_LEDS_BF ; LEDs back and forth
clr AKKU3 ; "TM1638
DEMO", Text block 0
rcall TM1638_PRINT_MOVETEXT
rcall TM1638_LEDS_BF ; LEDs back and forth
;=======================================================================
LOOP ; (LOOP is not an address!) ; Main Loop
rcall TM1638_CLEAR
ldi AKKU3,
4 ; "TEST
KEY", Text block 4
rcall TM1638_PRINT_TXT8
LOOP ; TEST KEY
loop
rcall delay500ms ; if S1+S8 are pushed continuously
clr BUTTONS
REPEAT
rcall TM1638_KEYPAD ; check the TM1638 buttons
UNTIL BUTTONS <> #0 ; wait until any button pressed
mov AKKU,BUTTONS ; to check
more than one button
EXITIF AKKU == #S18 ; exit if
both S1 and S8 are pressed
rcall TM1638_CLEAR ; test and display all keys separately
IF BUTTONS, S1
ldi TM1638_SEGM_BYTE,'1'
ldi TM1638_GRID_BYTE,0 ; left most
digit
ELSEIF BUTTONS, S2
ldi TM1638_SEGM_BYTE,'2'
ldi TM1638_GRID_BYTE,2 ; 2nd digit
ELSEIF BUTTONS, S3
ldi TM1638_SEGM_BYTE,'3'
ldi TM1638_GRID_BYTE,4 ; 3rd digit
ELSEIF BUTTONS, S4
ldi TM1638_SEGM_BYTE,'4'
ldi TM1638_GRID_BYTE,6 ; 4th digit
ELSEIF BUTTONS, S5
ldi TM1638_SEGM_BYTE,'5'
ldi TM1638_GRID_BYTE,8 ; 5th digit
ELSEIF BUTTONS, S6
ldi TM1638_SEGM_BYTE,'6'
ldi TM1638_GRID_BYTE,10 ; 6th digit
ELSEIF BUTTONS, S7
ldi TM1638_SEGM_BYTE,'7'
ldi TM1638_GRID_BYTE,12 ; 7th digit
ELSEIF BUTTONS, S8
ldi TM1638_SEGM_BYTE,'8'
ldi TM1638_GRID_BYTE,14 ; 8th digit
ELSE
ldi TM1638_SEGM_BYTE,'
'
ldi TM1638_GRID_BYTE,0 ; 1st digit
ENDI
rcall TM1638_PRINT_CHAR
ENDL
LOOP ; now loop
the various demo programs
rcall TM1638_CLEAR
ldi AKKU3,
3 ;
"SELECT..", Text block 3
rcall TM1638_PRINT_TXT8
rcall delay500ms ; if S1+S8 are pushed continuously
clr BUTTONS
REPEAT
rcall TM1638_KEYPAD ; check the TM1638 buttons
UNTIL BUTTONS <> #0 ; wait until any button pressed
EXITIF BUTTONS,
S8 ; button S8 leaves demos
to TEST KEY
; select demo
by button S1..S7
IF BUTTONS, S1
FOR COUNT := #3
rcall TM1638_TWIST_CW ; twist LEDs cw
ENDF
rcall TM1638_CLEAR
FOR COUNT := #3
rcall TM1638_TWIST_CCW ; twist LEDs ccw
ENDF
rcall TM1638_CLEAR
rcall TM1638_LEDS_BF ; LEDs back and forth
ELSEIF BUTTONS, S2
clr AKKU3 ; "LEDS DIM", Text block 0
rcall TM1638_PRINT_TXT8
FOR AKKU2
:= #1 ; DIM LEDs 1x
(or 2x)
FOR COUNT := #7 ; step darker
mov AKKU,
COUNT
rcall TM1638_BRIGHTNESS
rcall Delay500ms
ENDF
REPEAT ; step brighter again
mov AKKU, COUNT
rcall TM1638_BRIGHTNESS
rcall Delay500ms
subi COUNT,-1
UNTIL COUNT > #7
ENDF
rcall TM1638_LEDS_BF ; LEDs back and forth
ELSEIF BUTTONS, S3
ldi AKKU3,
1 ; Textblock "BINARY
COUNTER"
rcall TM1638_PRINT_MOVETEXT
clr BUTTONS
rcall TM1638_COUNT_BIN
rcall Delay1s
rcall TM1638_LEDS_BF ; LEDs back and forth
ELSEIF BUTTONS, S4
ldi AKKU3,
2 ; Textblock
"HEXACECIMAL COUNTER"
rcall TM1638_PRINT_MOVETEXT
clr BUTTONS
rcall TM1638_COUNT_HEX
rcall Delay1s
rcall TM1638_LEDS_BF ; LEDs back and forth
ELSEIF BUTTONS, S5
ldi AKKU3,
3 ; Textblock "DECIMAL
COUNTER"
rcall TM1638_PRINT_MOVETEXT
clr BUTTONS
rcall TM1638_COUNT_DEC
rcall Delay1s
rcall TM1638_LEDS_BF ; LEDs back and forth
ELSEIF BUTTONS, S6
; S5 = take split time, can be repeated
; S6 = continue elapsed time
; S8 = exit split time or elapsed time and
jump to SELECT loop
ldi AKKU3,
4 ; Textblock "ELAPSED
TIME"
rcall TM1638_PRINT_MOVETEXT
rcall TM1638_CLEAR
ldi yl,low(clk10ms) ; begin of
clock values in SRAM
ldi yh,high(clk10ms)
LOOP ; Elapsed time loop
clr BUTTONS
REPEAT
rcall TM1638_PRINT_TIME ; update elapsed clock time
rcall TM1638_KEYPAD ; check the
TM1638 buttons
UNTIL BUTTONS <> #0 ; wait until any button pressed
IF BUTTONS, S5 ; take split time
ldi AKKU,1
std y+10,AKKU ; mark split time
rcall TM1638_CLEAR
LOOP
clr BUTTONS
REPEAT
rcall TM1638_PRINT_SPLIT ; show split time
rcall TM1638_KEYPAD ; check the
TM1638 buttons
UNTIL BUTTONS <>
#0 ; wait until any button pressed
IF BUTTONS, S5 ; take
another split time shot
ldi AKKU,1
std y+10,AKKU ; mark split time again
ENDI
EXITIF BUTTONS, S6 ; back to
elapsed time
EXITIF BUTTONS, S8 ; leave
elapsed time to SELECT
ENDL
EXITIF BUTTONS, S6 ; back to
elapsed time
EXITIF BUTTONS, S8 ; leave
elapsed time to SELECT
ENDI
EXITIF BUTTONS, S8 ; leave
elapsed time to SELECT
ENDL
rcall TM1638_LEDS_BF ; LEDs back and forth
ELSEIF BUTTONS, S7 ; show the real-time clock until S8
; S3 = hour settings
; S4 = minute settings
; S5 = reset seconds, but only within
hrs/min settings
; S1 = decrement hrs/min, can hold down
for successive decrement
; S2 = increment hrs/min, can hold down
for successive increment
; S7 = leave settings, but stay in the
CLOCK loop and prevent S1/S2/S5
; S8 = exit clock time and jump to SELECT
loop
ldi AKKU3,
5 ; Textblock
"CLOCK TIME"
rcall TM1638_PRINT_MOVETEXT
rcall TM1638_CLEAR
ldi yl,low(clk10ms) ; begin of
clock values in SRAM
ldi yh,high(clk10ms)
LOOP ; CLOCK loop
clr BUTTONS
REPEAT
rcall TM1638_PRINT_CLOCK ; update clock time
rcall TM1638_KEYPAD ; check the
TM1638 buttons
UNTIL
BUTTONS <> #0 ; wait until
any button pressed
IF BUTTONS, S3 ; set hours
LOOP ; loop until S4, S7 or S8
clr BUTTONS
REPEAT
rcall TM1638_PRINT_CLOCK ; update clock time
rcall TM1638_KEYPAD ; check the
TM1638 buttons
UNTIL BUTTONS <>
#0 ; wait until any button pressed
IF BUTTONS, S2 ; increment
ldd AKKU,y+3 ; get hours
inc AKKU
std y+13,AKKU
IF AKKU > #23
clr AKKU
std y+13,AKKU ; reset hrs
ENDI
ldd AKKU,y+13
std y+3,AKKU ; restore hours
ELSEIF BUTTONS, S1 ; decrement
ldd AKKU,y+3
subi AKKU,1 ; (dec would
not affect CY)
std y+13,AKKU
IF C
ldi AKKU,23
std y+13,AKKU ; roll over
ENDI
ldd AKKU,y+13
std y+3,AKKU ; restore hours
ELSEIF BUTTONS, S5 ; reset seconds
ldi AKKU,1
std y+9,AKKU ; mark reset seconds
ENDI
rcall TM1638_PRINT_CLOCK ; update clock time
EXITIF
BUTTONS, S8 ; exit clock
time
EXITIF BUTTONS, S7 ; exit clock settings
EXITIF BUTTONS, S4 ; to switch to minutes
rcall delay500ms ; for S1/S2
repeat cycle
ENDL
ELSEIF BUTTONS, S4 ; set minutes
LOOP ; loop until
S3, S7 or S8
clr BUTTONS
REPEAT
rcall TM1638_PRINT_CLOCK ; update clock time
rcall TM1638_KEYPAD ; check the
TM1638 buttons
UNTIL BUTTONS <>
#0 ; wait until any button pressed
IF BUTTONS, S2 ; increment
ldd AKKU,y+2
inc AKKU
std y+12,AKKU
IF AKKU > #59
clr AKKU
std y+12,AKKU ; reset min
ENDI
ldd AKKU,y+12
std y+2,AKKU ; restore
minutes
ELSEIF BUTTONS, S1 ; decrement
ldd AKKU,y+2 ; min
subi AKKU,1 ; (dec would
not affect CY)
std y+12,AKKU
IF C
ldi AKKU,59
std y+12,AKKU ; roll over
ENDI
ldd AKKU,y+12
std y+2,AKKU ; restore
minutes
ELSEIF BUTTONS, S5 ; reset seconds
ldi AKKU,1
std y+9,AKKU ; mark reset seconds
ENDI
rcall TM1638_PRINT_CLOCK ; update clock time
EXITIF BUTTONS, S8 ; exit clock time
EXITIF BUTTONS, S7 ; exit clock settings
EXITIF BUTTONS, S3 ; to switch
to hours
rcall delay500ms ; for S1/S2
repeat cycle
ENDL
ENDI
EXITIF BUTTONS, S8 ; leave CLOCK
ENDL
EXITIF BUTTONS, S8 ; leave CLOCK to SELECT
rcall TM1638_LEDS_BF ; LEDs back and forth
ENDI ; end of
selected loops
ENDL
ENDL ; END OF MAIN LOOP
;=======================================================================
; Subroutines
;=======================================================================
;
; LED chains
back and forth
;
TM1638_LEDS_BF:
rcall TM1638_LEDS_L
rcall TM1638_LEDS_R
ret
;=======================================================================
;
; LED chain
to the right
;
TM1638_LEDS_R:
push COUNT
ldi TM1638_GRID_BYTE,
0x01 ; first LED address
FOR COUNT := #8
ldi TM1638_SEGM_BYTE,1 ; LED ON
rcall TM1638_SEND_DATA
rcall Delay100ms
clr TM1638_SEGM_BYTE ; LED OFF
rcall TM1638_SEND_DATA
subi TM1638_GRID_BYTE,-2 ; next LED
address
ENDF
pop COUNT
ret
;=======================================================================
;
; LED chain
to the left
;
TM1638_LEDS_L:
push COUNT
ldi TM1638_GRID_BYTE,
0x0F ; first LED address
FOR COUNT := #8
ldi TM1638_SEGM_BYTE,1 ; LED ON
rcall TM1638_SEND_DATA
rcall Delay100ms
clr TM1638_SEGM_BYTE ; LED OFF
rcall TM1638_SEND_DATA
subi TM1638_GRID_BYTE,2 ; next LED
address
ENDF
pop COUNT
ret
;=======================================================================
;
; binary
counter, 8 bit 0x00 through 0xff
;
TM1638_COUNT_BIN:
push AKKU
clr AKKU
REPEAT
rcall TM1638_PRINT_BIN ; print value in AKKU
rcall Delay100ms
rcall TM1638_KEYPAD ; check the TM1638 buttons
EXITIF BUTTONS, S8 ; button S8 leaves counter demo
inc AKKU
UNTIL AKKU == #0
pop AKKU
ret
;=======================================================================
;
; hexadecimal
counter, 16 bit AKKU2/AKKU, 0x0000 through 0xffff
;
TM1638_COUNT_HEX:
push AKKU
push AKKU2
clr AKKU
clr AKKU2
REPEAT
REPEAT
rcall TM1638_PRINT_HEX ; print value
IF AKKU <> #0xff
rcall Delay10ms ; to prevent
a delay during carry
ENDI
rcall TM1638_KEYPAD ; check the TM1638 buttons
EXITIF BUTTONS, S8 ; button S8 leaves counter demo
inc AKKU
UNTIL AKKU == #0 ; carry
inc AKKU2
EXITIF BUTTONS, S8 ; need 2nd button S8 test
to leave
rcall TM1638_PRINT_HEX ; print value
rcall Delay10ms
;EXITIF AKKU2
== #0x10 ; exit demo at 0x1000
UNTIL AKKU2 == #0
pop AKKU2
pop AKKU
ret
;=======================================================================
;
; decimal
counter, 16 bit
;
TM1638_COUNT_DEC:
;cli
push AKKU
push AKKU2
push AKKU3
push XL
push XH
clr XL
clr XH
REPEAT
mov AKKU2,
XL
mov AKKU3,
XH
rcall TM1638_PRINT_DEC ; print values in AKKU2 and AKKU3
; as 16 bit
number (LO and HI-Byte)
rcall Delay10ms
;EXITIF XH >= #8 ; stop at max 2048 for the demo
rcall TM1638_KEYPAD ; check the TM1638 buttons
EXITIF BUTTONS, S8 ; button S8 leaves counter demo
adiw XH:XL,1
UNTIL Z ; maximum
would be all 16 bits
pop XH
pop XL
pop AKKU3
pop AKKU2
pop AKKU
;sei
ret
;=======================================================================
;
; twist arround
CW from segment a through f
; EH:
replaced inner REPEAT loop by a FOR loop
;
TM1638_TWIST_CW:
push AKKU
push COUNT
ldi AKKU,
1 ; start with
segment a
clr TM1638_GRID_BYTE
REPEAT
FOR COUNT := #8
mov TM1638_SEGM_BYTE,AKKU
rcall TM1638_SEND_DATA ; activates only one LED
; position is
given by GRID_BYTE (digit)
; and
SEGM_BYTE (LED segment)
subi TM1638_GRID_BYTE,-2
ENDF
rcall delay100ms
clr TM1638_GRID_BYTE
rol AKKU ; next LED segment
;UNTIL AKKU == #0b01000000
UNTIL AKKU,6 ; until
segment g (not shown)
pop COUNT
pop AKKU
ret
;=======================================================================
;
; twist
arround CCW from segment f through a
; EH: replaced
inner REPEAT loop by a FOR loop
;
TM1638_TWIST_CCW:
push AKKU
push COUNT
ldi AKKU,
0b00100000 ; start with
segment f
clr TM1638_GRID_BYTE
REPEAT
FOR COUNT := #8
mov TM1638_SEGM_BYTE,AKKU
rcall TM1638_SEND_DATA ; activates only one LED
; position is
given by GRID_BYTE (digit)
; and
SEGM_BYTE (LED segment)
subi TM1638_GRID_BYTE,-2
ENDF
rcall delay100ms
clr TM1638_GRID_BYTE
ror AKKU ; next LED segment
UNTIL C ; until
shifted out
pop COUNT
pop AKKU
ret
;=======================================================================
;
TM1638_PRINT_TIME - elapsed time HH.MM.SS.MS is located in SRAM
; leading
zero of HH is suppressed (replaced by space character)
; 8 LEDs used
for overflow of 100s hours
; the right
most digits show the 10ms read during reset
;
TM1638_PRINT_TIME: ; elapsed time
push AKKU2 ; data from
SRAM
push AKKU3 ; digit
position
push COUNT
push yl
push yh
ldi yl,low(cnthrs+2) ; get HHH:MM:SS from SRAM
ldi yh,high(cnthrs+2)
ld AKKU2,-y ; handle 100s
of hours first
; ldi AKKU2,3 ;
**** test only to show that it works ...
ldi TM1638_GRID_BYTE,
0x01 ; address LED #8 (right
most) = 1*100 hrs
FOR COUNT := #8
IF COUNT == AKKU2
ldi TM1638_SEGM_BYTE,1 ; LED ON
ELSE
clr TM1638_SEGM_BYTE ; LED OFF
ENDI
rcall TM1638_SEND_DATA ; set LED off/on
subi TM1638_GRID_BYTE,-2 ; next LED
address
ENDF
mov LEADZ,
TRUE ; prepare
leading zero for 1st digit
clr AKKU3 ; start at
left most position
FOR COUNT := #4
ldi TM1638_SEGM_BYTE,'0'; prepare
AKKU = '0'
ld AKKU2,-y ; get HH, MM,
SS and 10 ms from SRAM
REPEAT
inc TM1638_SEGM_BYTE
subi AKKU2,
10
UNTIL C
subi AKKU2,
-10
dec TM1638_SEGM_BYTE ; correct the last inc
IF LEADZ == TRUE ; must be 1st position
IF TM1638_SEGM_BYTE
== #'0'
ldi TM1638_SEGM_BYTE,' '
ELSE
clr LEADZ ; decimal
place was 1-9
ENDI
ENDI
mov TM1638_GRID_BYTE,AKKU3
rcall TM1638_PRINT_CHAR
clr LEADZ ; no longer
leading zeros
subi AKKU3,-2 ; next digit position
ldi TM1638_SEGM_BYTE,'0' ; prepare AKKU = '0'
add TM1638_SEGM_BYTE,AKKU2 ; add
remainder
IF AKKU3
<> #0x0e ; not the
last digit
ori TM1638_SEGM_BYTE,0x80 ; add DP to
split digits
ENDI
mov TM1638_GRID_BYTE,AKKU3
rcall TM1638_PRINT_CHAR
subi AKKU3,-2 ; next digit position
ENDF
pop yh
pop yl
pop COUNT
pop AKKU3
pop AKKU2
ret
;=======================================================================
;
TM1638_PRINT_SPLIT - split time HH.MM.SS.MS is located in SRAM
; leading
zero of HH is suppressed (replaced by space character),
; 8 LEDs used
for overflow of 100s hours (from right to left),
; just the Y
pointer is different from TM1638_PRINT_TIME
;
TM1638_PRINT_SPLIT:
push AKKU2 ; data from
SRAM
push AKKU3 ; digit
position
push COUNT
push yl
push yh
ldi yl,low(splhrs+2) ; get HHH:MM:SS from SRAM
ldi yh,high(splhrs+2)
ld AKKU2,-y ; handle 100s
of hours first
ldi TM1638_GRID_BYTE,
0x01 ; address LED #8 (right
most) = 1*100 hrs
FOR COUNT := #8
IF COUNT == AKKU2
ldi TM1638_SEGM_BYTE,1 ; LED ON
ELSE
clr TM1638_SEGM_BYTE ; LED OFF
ENDI
rcall TM1638_SEND_DATA ; set LED off/on
subi TM1638_GRID_BYTE,-2 ; next LED
address
ENDF
mov LEADZ,
TRUE ; prepare
leading zero for 1st digit
clr AKKU3 ; start at
left most position
FOR COUNT := #4
ldi TM1638_SEGM_BYTE,'0'; prepare
AKKU = '0'
ld AKKU2,-y ; get HH, MM,
SS and 10 ms from SRAM
REPEAT
inc TM1638_SEGM_BYTE
subi AKKU2,
10
UNTIL C
subi AKKU2,
-10
dec TM1638_SEGM_BYTE ; correct the last inc
IF LEADZ == TRUE ; must be 1st position
IF TM1638_SEGM_BYTE
== #'0'
ldi TM1638_SEGM_BYTE,' '
ELSE
clr LEADZ ; decimal place
was 1-9
ENDI
ENDI
mov TM1638_GRID_BYTE,AKKU3
rcall TM1638_PRINT_CHAR
clr LEADZ ; no longer
leading zeros
subi AKKU3,-2 ; next digit position
ldi TM1638_SEGM_BYTE,'0' ; prepare AKKU = '0'
add TM1638_SEGM_BYTE,AKKU2 ; add remainder
IF AKKU3
<> #0x0e ; not the
last digit
ori TM1638_SEGM_BYTE,0x80 ; add DP to
split digits
ENDI
mov TM1638_GRID_BYTE,AKKU3
rcall TM1638_PRINT_CHAR
subi AKKU3,-2 ; next digit position
ENDF
pop yh
pop yl
pop COUNT
pop AKKU3
pop AKKU2
ret
;=======================================================================
;
TM1638_PRINT_CLOCK - clock time HH:MM:SS is located in SRAM
; leading
zero of HH is suppressed
; (similar to
TM1638_PRINT_TIME)
;
TM1638_PRINT_CLOCK:
push AKKU2 ; data from
SRAM
push AKKU3 ; digit
position
push COUNT
push yl
push yh
ldi yl,low(clkhrs+1) ; get HH:MM:SS from SRAM
ldi yh,high(clkhrs+1)
mov LEADZ,
TRUE ; prepare
leading zero for 1st digit
clr AKKU3 ; start at left
most position
FOR COUNT := #3
ldi TM1638_SEGM_BYTE,'0'; prepare
di9git = '0'
ld AKKU2,-y ; get HH, MM
and SS from SRAM
REPEAT
inc TM1638_SEGM_BYTE
subi AKKU2,
10
UNTIL C
subi AKKU2,
-10
dec TM1638_SEGM_BYTE ; correct the last inc
IF LEADZ == TRUE ; must be 1st position
IF TM1638_SEGM_BYTE
== #'0'
ldi TM1638_SEGM_BYTE,' '
ELSE
clr LEADZ ; decimal
place was 1-9
ENDI
ENDI
mov TM1638_GRID_BYTE,AKKU3
rcall TM1638_PRINT_CHAR
clr LEADZ ; no longer
leading zeros
subi AKKU3,-2 ; next digit position
ldi TM1638_SEGM_BYTE,'0' ; prepare digit = '0'
add TM1638_SEGM_BYTE,AKKU2 ; add
remainder
mov TM1638_GRID_BYTE,AKKU3
rcall TM1638_PRINT_CHAR
subi AKKU3,-2 ; next digit position
EXITIF AKKU3 > #0x0e ; all positions done
ldi TM1638_SEGM_BYTE,'-' ; print separator
mov TM1638_GRID_BYTE,AKKU3
rcall TM1638_PRINT_CHAR
subi AKKU3,-2 ; next digit position
ENDF
pop yh
pop yl
pop COUNT
pop AKKU3
pop AKKU2
ret
;=======================================================================
; other
subroutines and TM1638 character font:
; TM1638
library, compiled from "tm1638cc.inc_EH.s" using label prefix _I:
.INCLUDE
"tm1638cc.inc_EH.asm"
; delay
subroutines, compiled from "tm1638cc_delay_EH.s", label prefix _D:
.INCLUDE
"tm1638cc_delay_EH.asm"
; interrupt
based timer, compiled from "tm1638cc_timer.s", label prefix _T:
.INCLUDE
"tm1638cc_timer_EH.asm"
; NOTE: in
general all included .asm files being generated by s'AVR
; must use
DIFFERENT label prefixes (could be any from _A through _Z)
.INCLUDE
"tm1638cc_font.inc" ; TM1638
character font
;=======================================================================
; constant
text:
MOVETEXT: ; 35+1
characters each
.db " TM1638 DEMO ",0 ; TEXT_BLOCK 0
.db " BINARY COUNTER ",0 ; TEXT_BLOCK 1
.db " HEXADECIMAL COUNTER ",0 ; TEXT_BLOCK 2
.db " DECIMAL COUNTER ",0 ; TEXT_BLOCK 3
.db " ELAPSED TIME ",0,0,0,0,0,0,0,0,0 ; TEXT BLOCK 4
.db " CLOCK TIME ",0,0,0,0,0,0,0,0,0,0,0 ; TEXT BLOCK 5
TEXT10: ; 8+2 characters each
.db "LEDS
DIM",0,0 ; TEXT10,
Block 0
.db
"88888888",0,0 ; TEXT10, Block 1, showing all 7 segments w/o DP
.db
"(-88.88)",0,0 ; TEXT10,
Block 2, showing extra characters ( - . )
.db
"SELECT..",0,0 ; TEXT10, Block 3, select demo by button
.db "TEST KEY",0,0 ; TEXT10, Block 4, test keys
.DSEG
.ORG SRAM_START ; 0x0100
; keep the
next 2x 4 bytes together (being addressed by YH:YL)
clk10ms: .db 0 ; 0 count 10ms clock time
clksec: .db 0 ; 1 clock seconds
clkmin: .db 0 ; 2 clock minutes
clkhrs: .db 0 ; 3 clock hours
cnt10ms: .db 0 ; 4 count 10ms elapsed time
cntsec: .db 0 ; 5 count seconds
cntmin: .db 0 ; 6 count minutes
cnthrs: .db 0 ; 7 count hours
cnthrsh: .db 0 ; 8 count 100s of hrs, shown by LEDs 1
through 8
rstsec: .db 0 ; 9 = 1 indicates that seconds should be
reset
split: .db 0 ; 10 = 1 indicates to take split time
spare1: .db 0 ; 11 spare
setmin: .db 0 ; 12 used to set minutes
sethrs: .db 0 ; 13 used to set hours
spl10ms: .db 0 ; 14 store 10ms split time
splsec: .db 0 ; 15 store seconds
splmin: .db 0 ; 16 store minutes
splhrs: .db 0 ; 17 store hours
splhrsh: .db 0 ; 18 store 100s of hrs, shown by LEDs 1
through 8
spare2: .db 0 ; 19 spare
.EXIT