What has six legs and is very annoying? Well, lots of things I guess. But now there is one based on the 6-pin ATtiny10 microcontroller.
Basically it does this:
1. Lies in wait until it detects a remote control signal.
2. Records the signal and waits for 30 seconds.
3. Resends the signal.
4. Plays a little tune you may have heard before.
Why is that so annoying? Imagine sitting down to watch some TV. You hit the power button on your remote. 30 seconds later the TV unexpectedly turns off. As if that weren't enough, you then have the opportunity to hear a short, square-wave rendition of your favorite song.
Here is a little video you should watch:
How to make one
On the off chance that you actually want one of these, here is how to make one. The parts you need include:
1. ATtiny10
2. little circuit board - I was lucky to find a breakout board with some pads on the bottom
3. IR receiver - 38kHz is probably the most common
4. piezo speaker
5. IR LED - 940nm or so
6. 3.6V lithium button cell - or any other power source you have
7. power capacitor - I used a 100uF electrolytic
8. resistors - 100, 1k, 10k x2
And here is the beautiful schematic made with MSPaint:
And here are a couple pictures of the one I made:
But wait! Before you go putting it all together, remember that you have to be able to program the thing. This hardware setup is not programmer friendly, so make sure you have the program on the chip before soldering it all. I soldered the chip onto the breakout board, programmed it, then put the rest on.
Writing the code presented a variety of challenges. I repeatedly went over the 1024 byte limit and had to optimize things a bit. Also, with only 32 bytes of ram I had to be very careful. I ended up using 22 of those bytes to hold the timing and sequence information for the IR signal. The stack didn't use more than 8 bytes anywhere, which left me with 2 extra peace of mind bytes.
The assembly code is included at the end of this page. It is easy to change the tune or delay intervals, but you will have to dig your way through the code to do so. Some things to note are:
- The tiny10 goes into power-down sleep mode while it waits, so it won't burn through your battery.
- It will record up to 64 bits plus a header pulse as long as nothing is longer than about 12ms. This covers any of the common remote protocols, as far as I know.
- It records four timing values: header on, header off, long on, short on, long off, short off.
--------------------------------------------------------
here is the assembly code
--------------------------------------------------------
;
; The rick rolling mosquito
;
; Copyright 2012 Eric Heisler
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License version 3 as published by
; the Free Software Foundation.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; receives data up to 64 bits plus a header
; waits for 30 sec
; transmits the received data
; waits a second
; rick rolls
;
; >pin 1(PB0) piezo
; >pin 3(PB1) tx
; >pin 4(PB2) rx
; >pin 6(PB3) reset
;
;
; registers
; r16-18 are for temp use
.DEF rinLength = r19 ; number of bits
.DEF rinstop = r20 ; flags: bit0-stop receiving (timed out), 1-confirmed 1 on, 2-confirmed 1 off
.DEF rlongshort = r21 ; the longest or shortest length read from ram
.DEF rrxtimer = r22 ; for timing rx bits
.DEF rseqbitmask = r23 ; holds a useful bitmask
.DEF rtxonseq = r24 ; holds the current on seq
.DEF rtxoffseq = r25 ; holds the current off seq
.DEF rnotelength = r26 ; the time to play the note
.EQU rxpin = PB2
.EQU txpin = PB1
.EQU sppin = PB0
.EQU noteAb = 9632
.EQU noteBb = 8580
.EQU noteC = 7644
.EQU noteDb = 7215
.EQU noteEb = 6428
.EQU noteF = 5728
.EQU noteAbp = 4816
.EQU onebeat = 3
.EQU twobeat = 6
.EQU threebeat = 9
.EQU fourbeat = 12
.EQU sixbeat = 18
.EQU littlepause = 3
; data stored in SRAM
; these are SRAM addresses
; the start signal length
.EQU startOn = SRAM_START
.EQU startOff = SRAM_START+1
; longest on and off times
.EQU longon = SRAM_START+2
.EQU longoff = SRAM_START+3
.EQU shorton = SRAM_START+4
.EQU shortoff = SRAM_START+5
.EQU onseq1 = SRAM_START+6
.EQU onseq2 = SRAM_START+7
.EQU onseq3 = SRAM_START+8
.EQU onseq4 = SRAM_START+9
.EQU onseq5 = SRAM_START+10
.EQU onseq6 = SRAM_START+11
.EQU onseq7 = SRAM_START+12
.EQU onseq8 = SRAM_START+13
.EQU offseq1 = SRAM_START+14
.EQU offseq2 = SRAM_START+15
.EQU offseq3 = SRAM_START+16
.EQU offseq4 = SRAM_START+17
.EQU offseq5 = SRAM_START+18
.EQU offseq6 = SRAM_START+19
.EQU offseq7 = SRAM_START+20
.EQU offseq8 = SRAM_START+21
.CSEG ; code section
.ORG $0000 ; the start address
; interrupt vectors
rjmp main ; reset vector
reti ; external interrupt 0
reti ; pin change
reti ; timer input capture
reti ; timer overflow
reti ; timer compare match A
reti ; timer compare match B
reti ; analog comparator
reti ; watchdog timer
reti ; Vcc voltage level monitor
reti ; ADC conversion complete
; interrupt service routines
;isr_pcint:
;reti ; return and enable int
main:
; set up the stack
ldi r16, HIGH(RAMEND)
out SPH, r16
ldi r16, LOW(RAMEND)
out SPL, r16
; set clock divider
ldi r16, 0x00 ; clock divided by 1
ldi r17, 0xD8 ; the key for CCP
out CCP, r17 ; Configuration Change Protection, allows protected changes
out CLKPSR, r16 ; sets the clock divider
; setup pins
ldi r16, (1<<txpin)|(1<<sppin)
out DDRB, r16
; setup interrupt
ldi r16, 1
out PCICR, r16
ldi r16, (1<<PCINT2)
out PCMSK, r16
; enable sleep
ldi r16, (1<<SM1)|(1<<SE) ; power down sleep
out SMCR, r16
; delay for a second to let things settle
ldi r16, 0x1F
rcall tripledelayr16
rcall resetData
sei
; main loop
loop:
; wait for input
sleep
nop
cli
; if it was just noise
sbic PINB, rxpin
rjmp endLoop
; Receive
rcall receive
;rcall adjustdata
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;wait about 30 seconds
ldi r16, 0xFF
rcall tripledelayr16
ldi r16, 0xFF
rcall tripledelayr16
ldi r16, 0xFF
rcall tripledelayr16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; transmit the sequence
rcall transmit
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; wait
ldi r16, 0x1F
rcall tripledelayr16
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rcall play
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
endLoop:
rcall resetData
sei
rjmp loop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
resetData:
clr rinLength
clr rinStop
ldi rseqbitmask, 1
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
receive:
; at this point we are in the start bit
; wait for rise
rcall timeOn
sts startOn, rrxtimer
; wait for fall
rcall timeOff
sts startOff, rrxtimer
; time the first bit
rcall timeOn
sbrc rinStop, 0
rjmp finishedReceiving
ldi r18, 1
sts onseq1, r18
sts longon, rrxtimer
sts shorton, rrxtimer
rcall timeOff
sbrc rinStop, 0
rjmp finishedreceiving
ldi r18, 1
sts offseq1, r18
sts longoff, rrxtimer
sts shortoff, rrxtimer
inc rinlength
lsl rseqbitmask
; time the rest of the bits
receiveBits:
rcall timeOn
sbrc rinStop, 0
rjmp finishedReceiving
; load up the current sequence
lds rtxonseq, onseq1
lds rtxoffseq, offseq1
cpi rinLength, 8
brlo sequenceloaded
lds rtxonseq, onseq2
lds rtxoffseq, offseq2
cpi rinLength, 16
brlo sequenceloaded
lds rtxonseq, onseq3
lds rtxoffseq, offseq3
cpi rinLength, 24
brlo sequenceloaded
lds rtxonseq, onseq4
lds rtxoffseq, offseq4
cpi rinLength, 32
brlo sequenceloaded
lds rtxonseq, onseq5
lds rtxoffseq, offseq5
cpi rinLength, 40
brlo sequenceloaded
lds rtxonseq, onseq6
lds rtxoffseq, offseq6
cpi rinLength, 48
brlo sequenceloaded
lds rtxonseq, onseq7
lds rtxoffseq, offseq7
cpi rinLength, 56
brlo sequenceloaded
lds rtxonseq, onseq8
lds rtxoffseq, offseq8
sequenceloaded:
; check against longest
lds rlongshort, longon
cp rlongshort, rrxtimer
;not longer
brsh notlonger
;longer
mov r18, rlongshort
lsr r18
add r18, rlongshort
cp rrxtimer, r18
sbrs rinstop, 1
;new 1 level (more than 1.5*long)
brsh newonelevel
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;just a little longer. set as longest and set 1
setlongestandsetoneon:
sts longon, rrxtimer
setoneon:
or rtxonseq, rseqbitmask
rjmp onbitdone
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
newonelevel:
sbr rinstop, 2
; all previous bits must be zero
clr rtxonseq
sts onseq1, rtxonseq
sts onseq2, rtxonseq
sts onseq3, rtxonseq
sts onseq4, rtxonseq
sts onseq5, rtxonseq
sts onseq6, rtxonseq
sts onseq7, rtxonseq
sts onseq8, rtxonseq
rjmp setlongestandsetoneon
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
notlonger:
; compare against shortest
lds rlongshort, shorton
cp rlongshort, rrxtimer
brlo notlongersetvalue
sts shorton, rrxtimer
notlongersetvalue:
;if much shorter than longest
lds r18, longon
mov r17, r18
lsr r18
lsr r18
sub r17, r18
cp r17, rrxtimer
;zero bit if less than 0.75*long
brlo setoneon
setzeroon:
sbr rinstop, 2
mov r17, rseqbitmask
com r17
and rtxonseq, r17
onbitdone:
; the bit is set, now for the off time
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
rcall timeOff
sbrc rinStop, 0
rjmp offbitdone
; check against longest
lds rlongshort, longoff
cp rlongshort, rrxtimer
;not longer
brsh notlongeroff
;longer
mov r18, rlongshort
lsr r18
add r18, rlongshort
cp rrxtimer, r18
sbrs rinstop, 2
;new 1 level (more than 1.5*long)
brsh newoneleveloff
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;just a little longer. set as longest and set 1
setlongestandsetoneoff:
sts longoff, rrxtimer
setoneoff:
or rtxoffseq, rseqbitmask
rjmp offbitdone
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
newoneleveloff:
sbr rinstop, 4
clr rtxoffseq
sts offseq1, rtxoffseq
sts offseq2, rtxoffseq
sts offseq3, rtxoffseq
sts offseq4, rtxoffseq
sts offseq5, rtxoffseq
sts offseq6, rtxoffseq
sts offseq7, rtxoffseq
sts offseq8, rtxoffseq
rjmp setlongestandsetoneoff
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
notlongeroff:
; compare against shortest
lds rlongshort, shortoff
cp rlongshort, rrxtimer
brlo notlongersetvalueoff
sts shortoff, rrxtimer
notlongersetvalueoff:
;if much shorter than longest
lds r18, longoff
mov r17, r18
lsr r18
lsr r18
sub r17, r18
cp r17, rrxtimer
;zero bit if less than 0.75*long
brlo setoneoff
setzerooff:
sbr rinstop, 4
mov r17, rseqbitmask
com r17
and rtxoffseq, r17
offbitdone:
; store the sequence
cpi rinLength, 8
brlo stsseq1
cpi rinLength, 16
brlo stsseq2
cpi rinLength, 24
brlo stsseq3
cpi rinLength, 32
brlo stsseq4
cpi rinLength, 40
brlo stsseq5
cpi rinLength, 48
brlo stsseq6
cpi rinLength, 56
brlo stsseq7
rjmp stsseq8
stsseq1:
sts onseq1, rtxonseq
sts offseq1, rtxoffseq
rjmp sequencestored
stsseq2:
sts onseq2, rtxonseq
sts offseq2, rtxoffseq
rjmp sequencestored
stsseq3:
sts onseq3, rtxonseq
sts offseq3, rtxoffseq
rjmp sequencestored
stsseq4:
sts onseq4, rtxonseq
sts offseq4, rtxoffseq
rjmp sequencestored
stsseq5:
sts onseq5, rtxonseq
sts offseq5, rtxoffseq
rjmp sequencestored
stsseq6:
sts onseq6, rtxonseq
sts offseq6, rtxoffseq
rjmp sequencestored
stsseq7:
sts onseq7, rtxonseq
sts offseq7, rtxoffseq
rjmp sequencestored
stsseq8:
sts onseq8, rtxonseq
sts offseq8, rtxoffseq
sequencestored:
; the bit is set, now update count and bitmask and do the next bit
inc rinlength
cpi rinlength, 64
brsh finishedreceiving
sbrc rinstop, 0
rjmp finishedreceiving
lsl rseqbitmask
brne gobacktoreceivebits
ldi rseqbitmask, 1
gobacktoreceivebits:
rjmp receivebits
finishedReceiving:
ret
timeOn:
; each tic is 400 cycles(50us) timeout at 12ms
ldi rrxtimer, 0x00
timeOnLoop:
ldi r16, 131 ; 393 cycles
timeOnDelay:
subi r16, 1
brne timeOnDelay
inc rrxtimer
cpi rrxtimer, 0xFF
breq escapeReceive
sbis PINB, rxpin
rjmp timeOnLoop
ret
timeOff:
; each tic is 400 cycles(50us) timeout at 12ms
ldi rrxtimer, 0x00
timeOffLoop:
ldi r16, 131 ; 393 cycles
timeOffDelay:
subi r16, 1
brne timeOffDelay
inc rrxtimer
cpi rrxtimer, 0xFF
breq escapeReceive
sbic PINB, rxpin
rjmp timeOffLoop
ret
escapeReceive:
ldi rinStop, 1
ret
adjustdata:
; if not confirmed 1, average long and short
sbrs rinstop, 1
rjmp dontaverageon
lds r16, shorton
lds r17, longon
add r17, r16
lsr r17
sts shorton, r17
sts longon, r17
dontaverageon:
sbrs rinstop, 2
rjmp dontaverageoff
lds r16, shortoff
lds r17, longoff
add r17, r16
lsr r17
sts shortoff, r17
sts longoff, r17
dontaverageoff:
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
transmit:
; start on
lds rrxtimer, starton
rcall txtime
; start off
lds rrxtimer, startoff
rcall offtime
; then the data
ldi rinstop, 0xFF
txloadseq1:
lds rtxonseq, onseq1
lds rtxoffseq, offseq1
rjmp txbitloop
txloadseq2:
lds rtxonseq, onseq2
lds rtxoffseq, offseq2
rjmp txbitloop
txloadseq3:
lds rtxonseq, onseq3
lds rtxoffseq, offseq3
rjmp txbitloop
txloadseq4:
lds rtxonseq, onseq4
lds rtxoffseq, offseq4
rjmp txbitloop
txloadseq5:
lds rtxonseq, onseq5
lds rtxoffseq, offseq5
rjmp txbitloop
txloadseq6:
lds rtxonseq, onseq6
lds rtxoffseq, offseq6
rjmp txbitloop
txloadseq7:
lds rtxonseq, onseq7
lds rtxoffseq, offseq7
rjmp txbitloop
txloadseq8:
lds rtxonseq, onseq8
lds rtxoffseq, offseq8
rjmp txbitloop
txbitloop:
inc rinstop
cp rinstop, rinlength
brsh endtransmission
; tx on
lds rrxtimer, shorton
sbrc rtxonseq, 0
lds rrxtimer, longon
rcall txtime
; tx off
lds rrxtimer, shortoff
sbrc rtxoffseq, 0
lds rrxtimer, longoff
rcall offtime
cpi rinstop, 7
breq txloadseq2
cpi rinstop, 15
breq txloadseq3
cpi rinstop, 23
breq txloadseq4
cpi rinstop, 31
breq txloadseq5
cpi rinstop, 39
breq txloadseq6
cpi rinstop, 47
breq txloadseq7
cpi rinstop, 55
breq txloadseq8
lsr rtxonseq
lsr rtxoffseq
rjmp txbitloop
endtransmission:
ret
txtime:
ldi r17, (1<<txpin)
txtimeLoop:
; toggle txpin every 105 cycles
; do this 4 times for each tic
; use delayr16 with 32 (0x20) for 103 cycles (use 30(0x1E) with other stuff)
rcall txtoggle
rcall txtoggle
rcall txtoggle
rcall txtoggle
dec rrxtimer
brne txtimeLoop
cbi PORTB, txpin
ret
txtoggle:
ldi r16, 0x1B ; use 0x1B for about 100 cycles total.
rcall delayr16
in r18, PORTB
eor r18, r17
out PORTB, r18
ret
offtime:
; do nothing for rrxtimer * 400 cycles
ldi r16, 129
rcall delayr16
dec rrxtimer
brne offtime
ret
play:
; load each note and call playnote
; note is stored in r17:r16
; timing is stored in r18
;
; delay some time for rests
;
;notes:
;Ab Bb Db Bb F F Eb
;Ab Bb Db Bb Eb Eb Db
;Ab Bb Db Bb Db Eb C Bb Ab Ab Eb Db
;Ab Bb Db Bb F F Eb
;Ab Bb Db Bb Ab+ C Db C Bb
;Ab Bb Db Bb Db Eb C Bb Ab Ab Eb Db
;
;freq.
;Ab = 415.3
;Bb = 466.2
;Db = 554.4
;F = 698.3
;Eb = 622.3
;C = 523.3
;Ab+ = 830.6
;
;8MHz, 1prescaler
;Ab = 9632
;Bb = 8580
;Db = 7215
;F = 5728
;Eb = 6428
;C = 7644
;Ab+ = 4816
; setup timer
; CTC with prescaler 1
ldi r16, (1<<COM0A0)
out TCCR0A, r16
rcall playABDB
rcall playFFE
rcall playABDB
ldi rnotelength, twobeat
rcall playEb
ldi r16, littlepause
rcall tripledelayr16
rcall playEb
ldi r16, littlepause
rcall tripledelayr16
ldi rnotelength, sixbeat
rcall playDb
ldi r16, littlepause
rcall tripledelayr16
rcall playABDB
rcall playDECBAAED
rcall playABDB
rcall playFFE
rcall playABDB
ldi rnotelength, twobeat
rcall playAbp
ldi r16, littlepause
rcall tripledelayr16
rcall playC
ldi r16, littlepause
rcall tripledelayr16
ldi rnotelength, fourbeat
rcall playDb
ldi rnotelength, onebeat
rcall playC
rcall playBb
ldi r16, littlepause
rcall tripledelayr16
rcall playABDB
rcall playDECBAAED
ret
playFFE:
ldi rnotelength, twobeat
rcall playF
ldi r16, littlepause
rcall tripledelayr16
rcall playF
ldi r16, littlepause
rcall tripledelayr16
ldi rnotelength, sixbeat
rcall playEb
ldi r16, littlepause
rcall tripledelayr16
ret
playABDB:
ldi rnotelength, onebeat
rcall playAb
rcall playBb
rcall playDb
rcall playBb
ret
playDECBAAED:
ldi rnotelength, threebeat
rcall playDb
rcall playEb
ldi rnotelength, threebeat
rcall playC
ldi rnotelength, onebeat
rcall playBb
ldi rnotelength, twobeat
rcall playAb
ldi r16, littlepause
rcall tripledelayr16
rcall playAb
ldi rnotelength, fourbeat
rcall playEb
rcall playDb
ldi r16, littlepause
rcall tripledelayr16
ret
playAb:
ldi r17, HIGH(noteAb)
ldi r16, LOW(noteAb)
rcall playnote
ret
playBb:
ldi r17, HIGH(noteBb)
ldi r16, LOW(noteBb)
rcall playnote
ret
playC:
ldi r17, HIGH(noteC)
ldi r16, LOW(noteC)
rcall playnote
ret
playDb:
ldi r17, HIGH(noteDb)
ldi r16, LOW(noteDb)
rcall playnote
ret
playEb:
ldi r17, HIGH(noteEb)
ldi r16, LOW(noteEb)
rcall playnote
ret
playF:
ldi r17, HIGH(noteF)
ldi r16, LOW(noteF)
rcall playnote
ret
playAbp:
ldi r17, HIGH(noteAbp)
ldi r16, LOW(noteAbp)
rcall playnote
ret
playnote:
out OCR0AH, r17
out OCR0AL, r16
ldi r16, (1<<WGM02)|(1<<CS00) ;this turns it on
out TCCR0B, r16
mov r16, rnotelength
rcall tripledelayr16
ldi r16, (1<<WGM02) ;this turns it off
out TCCR0B, r16
ldi r16, 0
out PORTB, r16
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; utilities
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; short delay loop, 3 * r16 + 7 cycles (1~96us)
delayr16:
subi r16, 1
brne delayr16
ret
; long delay loop, 5 * r16 * 0xff * 0xff + 16 cycles (40642~10363361us)
tripledelayr16:
push r17
push r18
ldi r17, 0xFF
ldi r18, 0xFF
tripledelayr16Loop:
subi r18, 1
sbci r17, 0
sbci r16, 0
brne tripledelayr16Loop
pop r18
pop r17
ret
How do you actually program the chip? With an Arduino board or something?
ReplyDelete@ME:
ReplyDeleteI was able to modify your code to work on Attiny13a with some understanding on how it works.
I removed the clock divider part since attiny13 doesn't have CLKPSR. However, I have disabled the CKDIV8 fuse so it runs now at 4.8MHz
what freq are you running yours at? or is your code self adjusting to each IR protocol lengths?
@Fahad -
ReplyDeleteThe Attiny13 can do this much more easily than the tiny10 because it has 32 registers(not 16) and 64 bytes of SRAM (not 32), but most of this code should still work. The clock system is very different, but I guess you have that figured out.
This is running at 8MHz, so the 9.6MHz option for the tiny13 would be closer. This code actually measures and records the lengths of the signal's on and off times, so it shouldn't matter, but 9.6MHz will give you twice the resolution.
I think I have really come on the right place for getting the perfect info.
ReplyDeletesterling va mosquito control
The code may generate an error on the .DEF r26 as that may already be defined in the Attiny10 header file as 'XH'.
ReplyDeleteSolution: change the code as follows:
;.DEF rnotelength = r26 ; the time to play the note
#define rnotelength XH
For those (like me) who haven't worked with assembly, is there a way to convert this code into something more familiar in, say, Arduino IDE?
ReplyDelete@Ken Martin -
ReplyDeleteI don't know of an automatic way to convert assembly into something you could use in Arduino IDE. But it might be out there somewhere.
Although you could write the code in C, you would certainly run out of RAM and the program would be too big. The assembly I wrote uses almost every byte of available flash, RAM and registers. It even dedicates some of the registers to hold variables. But, if you want to use the code on a bigger chip, say an ATTiny85, you could certainly write it up in the Arduino IDE. It would look a whole lot simpler and could use libraries like Tone to handle the music.
I reused your code and made an IR earbud. I wanted to be able to hear IR data if it was being transmitted. Essentially I switched the piezo-buzzer to the IR output instead of playing the music. Thank you posting everything so far.
ReplyDelete