Christmas supercomputer
Note: it is the summer holidays DownUnder, so this blog (and YT channel) will be taking a little break for a month - see you in 2021!
Who doesn't love red and green flashing LEDs at Christmas? For the last couple of years we have had these little CR2032 driven ATTiny13 chips flashing a couple of 5mm LEDs strewn throughout the house (and outside).
The microcontrollers are running at 1MHz and they are mostly sleep, just pumping out alternate 1/8th second blips to the LEDs followed by a 4 second gap. In this guise the coin cells last around 6-9 months (!!), although they do get a bit dim towards the end of that run.
This year I decided to update the project, again using ATTiny13a chips, but this time ambling along at 128kHz (less power) which switch 1206 SMD LEDs (less power at 1/4W), but flashing more frequently (1/8th second on, 1/2 second off). So it will be very interesting to see how they last through the festive season and beyond. I can't remember if the original was coded in assembly or not, but this one sure is:
;
; Device: ATtiny13A, Package: 8-pin-PDIP_SOIC
;
; ______
; 1 / |8
; RESET o--| |--o VCC
; 2| |7
; PB3 o--| |--o PB2
; 3| |6
; PB4 o--| |--o PB1
; 4| |5
; GND o--| |--o PB0
; |_______|
;
.nolist
.include "tn13adef.inc" ; Define device ATtiny13A
.list
; **********************************
; R E G I S T E R S
; **********************************
.def rSreg = R15 ; Save/Restore status port
.def rmp = R16 ; Define multipurpose register
.def colour = R1
; **********************************
; S R A M
; **********************************
.dseg
.org SRAM_START
; **********************************
; C O D E
; **********************************
.cseg
.org 000000
; **********************************
; R E S E T & I N T - V E C T O R S
; **********************************
rjmp Main ; Reset vector
reti ; INT0
reti ; PCI0
reti ; OVF0
reti ; ERDY
reti ; ACI
reti ; OC0A
reti ; OC0B
rjmp mytimer_ISR ; watchdog timer interrupt
reti ; ADCC
; **********************************
; I N T - S E R V I C E R O U T .
; **********************************
; Add all interrupt service routines
mytimer_ISR:
; as I understand it, cli and sei are automatic on
; entry and exit respectively of ISR
in r16, SREG ; save SREG
push r16 ; do this if you want to use
finishisr:
pop r16 ; do this if you pushed SREG above
out SREG, r16 ; restore SREG
reti
; **********************************
; M A I N P R O G R A M I N I T
; **********************************
Main:
ldi rmp,Low(RAMEND)
out SPL,rmp ; Init LSB stack pointer
ldi r16, 0b00011000 ; output mode for PB3/4
out DDRB, r16
ldi r16, 0b00010000
mov colour, r16 ; red is on
; turn on PB4, enable internal pullups
; on the rest of the pins except PB3
ldi r16, 0b11110111
out PORTB, r16
; **********************************
; P R O G R A M L O O P
; **********************************
Loop:
rcall waitabit ; 1/16 second subroutine
rcall waitalot ; 1/2 second subroutine
rjmp Loop
waitabit:
wdr ; reset watchdog timer
ldi r16, 0b01000010 ; 1/8 second timer
out WDTCR, r16
rcall sleepnow ; sleep subroutine
rcall flipbit ; flip the led, if off then on, etc.
ret
waitalot:
wdr ; reset watchdog timer
ldi r16, 0b01000101 ; 1/2 second timer
out WDTCR, r16
rcall sleepnow ; sleep subroutine
rcall flipbit ; flip the leds
ret
sleepnow:
; sleep enable, power down mode
ldi r16, 0b00110000
out MCUCR, r16
; disable ADC
ldi r16, 0b00010000
out ADCSRA, r16
; disable interrupts to make sure the following
; timed sequence is not interrupted
cli
; disable BOD - must be done in a timed sequence
; as follows, write 1 to BODS and BODSE then within
; four clock cycles write 1 to BODS and 0 to BODSE
; then within three clock cycles enable sleep
; page 33 on the datasheet
ldi r16, 0b00000011
ldi r17, 0b00000010
out BODCR, r16
out BODCR, r17
sei
sleep
; sleep disable
ldi r16, 0b00000000
out MCUCR, r16
ret
flipbit:
in r16, pinb ; what is the state of the pins?
andi r16, 0b00011000 ; load red or green on
brbc 1, turnoff
testred:
mov r16, colour
ldi r17, 0b00001000
cp r16, r17
brbs 1, greenon
redon:
ldi r16, 0b00001000 ; set colour red
mov colour, r16 ; and make it so
ldi r16, 0b00001000
out portb, r16
rjmp finishflip
greenon:
ldi r16, 0b00010000 ; set colour green
mov colour, r16 ; and make it so
ldi r16, 0b00010000
out portb, r16
rjmp finishflip
turnoff:
ldi r16, 0b00000000
out portb, r16
finishflip:
ret
; End of source code
The only downside is that with the frantic flashing the place looks like an alien landing site or a Christmas super computer - good one!
In line with some other current projects, it is my solemn promise to make next year's batch from Pesky Padauk microcontrollers, probably the PMS150C.






