Skip to content

Instantly share code, notes, and snippets.

@shawnnapora
Last active July 30, 2022 06:40
Show Gist options
  • Save shawnnapora/c4a4e8892ea26184bc3c17021d4cba63 to your computer and use it in GitHub Desktop.
Save shawnnapora/c4a4e8892ea26184bc3c17021d4cba63 to your computer and use it in GitHub Desktop.
Euler problem 1 on ATTiny85
; If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The sum of these multiples is 23.
; Find the sum of all the multiples of 3 or 5 below 1000.
.include "tn85def.inc"
.def counter_lR = r24 ; adiw works against r24+
.def counter_hR = r25
.def zeroR = r1 ; so we can carry with adc since there's no adic
.def threeR = r18
.def fiveR = r19
.def result_lR = r20
.def result_hR = r21
.def result_sR = r22
.equ max = 999 ; multiples of 3 or 5 below 1000, but it will take action on the last element
.cseg
.org 0x00
setup:
ldi r16, (1<<PINB0) ; mask for pb0
out DDRB, r16 ; enable pb0 for output
; set up stack. SRAM starts at 0x60, so allocate 16 bytes for now. The stack grows downward.
; https://ww1.microchip.com/downloads/en/devicedoc/atmel-2586-avr-8-bit-microcontroller-attiny25-attiny45-attiny85_datasheet.pdf#G1.1179139
.equ stackStart = 0x70
ldi r16, HIGH(stackStart)
out SPH, r16
ldi r16, LOW(stackStart)
out SPL, r16
; zero our counters and results registers
clr counter_lR
clr counter_hR
clr zeroR
clr threeR
clr fiveR
clr result_lR
clr result_hR
clr result_sR
loop:
; increment counters
adiw counter_lR, 1
inc threeR
inc fiveR
; check divisibility by 3
cpi threeR, 3
brne check_five ; if our counter isn't 3, try 5 next
add result_lR, counter_lR ; otherwise add the result to our result counter
adc result_hR, counter_hR ; and carry the overflow from the lower byte add
adc result_sR, zeroR ; add the zero register to handle overflow from lower bytes
clr threeR ; reset the 3 counter to 0
cpi fiveR, 5 ; sometimes three and five will both need attention, but we shouldn't fall through and add again
brne check_counter
clr fiveR
rjmp check_counter
check_five:
cpi fiveR, 5
brne check_counter ; if our counter isn't 5, check our big counter
add result_lR, counter_lR
adc result_hR, counter_hR
adc result_sR, zeroR
clr fiveR
check_counter:
; check to see if counter is max (1000) yet, loop back if not
cpi counter_lR, LOW(max)
brne loop
cpi counter_hR, HIGH(max)
brne loop
; if we're here, we've hit our max and we're done with the above. it's time to blink an LED!
emit_answer:
.def val1R = r1
.def bitLoopR = r16
.def maskR = r17
.def delayR = r18
.def iLooplR = r24 ; sbiw works against register pairs for registers r24+
.def iLoophR = r25
.equ multVal = 15625 ; 4_000_000 loops to one second @8MHz, divided by 256 so one byte of all ones is a full second of delay
.equ shortDelay = 25 ; tenth of a second for short delay
.equ longDelay = 255 ; full second
mov val1R, result_lR
rcall write_byte
mov val1R, result_hR
rcall write_byte
mov val1R, result_sR
rcall write_byte
endLoop:
rjmp endLoop
write_byte:
ldi bitLoopR, 8 ; we're going to shift a byte, bit by bit
write_bits:
; first, toggle led off/on real quick to allow multiple on or off bytes to be visible
clr maskR ; zero our led register
ldi delayR, shortDelay
rcall write_delay
inc maskR
ldi delayR, shortDelay
rcall write_delay
; then write our bit
clr maskR ; zero our led register
lsr val1R ; shift val1R and store the LSB in the C flag
adc maskR, maskR ; with maskR zeroed, adc will just add the C flag
ldi delayR, longDelay
rcall write_delay
dec bitLoopR
brne write_bits
ret
write_delay: ; expects the delay value in delayR, mask in maskR, falls to delay overwriting oLooplR and oLoophR
out PORTB, maskR
delay: ; expects the delay value to be in delayR, overwrites oLooplR and oLoophR.
ldi iLooplR, LOW(multVal)
ldi iLoophR, HIGH(multVal)
delay_loop:
sbiw iLooplR, 1 ; word instruction to decrement register pair
brne delay_loop
dec delayR
brne delay
ret
[shawn@localhost avr]$ avra euler_0001.asm
AVRA: advanced AVR macro assembler Version 1.3.0 Build 1 (8 May 2010)
Copyright (C) 1998-2010. Check out README file for more info
AVRA is an open source assembler for Atmel AVR microcontroller family
It can be used as a replacement of 'AVRASM32.EXE' the original assembler
shipped with AVR Studio. We do not guarantee full compatibility for avra.
AVRA comes with NO WARRANTY, to the extent permitted by law.
You may redistribute copies of avra under the terms
of the GNU General Public License.
For more information about these matters, see the files named COPYING.
Pass 1...
tn85def.inc(44) : PRAGMA directives currently ignored
tn85def.inc(48) : PRAGMA directives currently ignored
tn85def.inc(53) : PRAGMA directives currently ignored
tn85def.inc(54) : PRAGMA directives currently ignored
tn85def.inc(647) : PRAGMA directives currently ignored
tn85def.inc(648) : PRAGMA directives currently ignored
tn85def.inc(649) : PRAGMA directives currently ignored
tn85def.inc(650) : PRAGMA directives currently ignored
euler_0001.asm(78) : Warning : r1 is already assigned to 'zeroR'!
euler_0001.asm(81) : Warning : r18 is already assigned to 'threeR'!
euler_0001.asm(82) : Warning : r24 is already assigned to 'counter_lR'!
euler_0001.asm(83) : Warning : r25 is already assigned to 'counter_hR'!
Pass 2...
tn85def.inc(44) : PRAGMA directives currently ignored
tn85def.inc(48) : PRAGMA directives currently ignored
tn85def.inc(53) : PRAGMA directives currently ignored
tn85def.inc(54) : PRAGMA directives currently ignored
tn85def.inc(647) : PRAGMA directives currently ignored
tn85def.inc(648) : PRAGMA directives currently ignored
tn85def.inc(649) : PRAGMA directives currently ignored
tn85def.inc(650) : PRAGMA directives currently ignored
done
Used memory blocks:
Code : Start = 0x0000, End = 0x0042, Length = 0x0043
Assembly complete with no errors (4 warnings).
Segment usage:
Code : 67 words (134 bytes)
Data : 0 bytes
EEPROM : 0 bytes
[shawn@localhost avr]$ sudo minipro -p ATTINY85 -w euler_0001.hex
[sudo] password for shawn:
Found TL866II+ 04.2.126 (0x27e)
Chip ID OK: 0x1E930B
Found Intel hex file.
Erasing... 0.01Sec OK
Writing Code... 1.06Sec OK
Reading Code... 0.44Sec OK
Verification OK
[shawn@localhost avr]$ python -c "print(0b0000000111000111011010000)"
233168
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment