.include "m1281def.inc"

; use increments of 4 for src_addr
; csma_seed = 8 x src_addr
.equ src_addr = $aaf0 ; place unique source address here
.equ csma_seed = low(src_addr)*$08 ; random backoff exponent - must be unique,<$0800 
.equ home_addr = $aabb ; local node des_addr
.equ pan_id = $abcd ; system pan_id
.equ retries = $38 ; high nibble = frame retries,low nibble = 2x(csma retries)
.equ channel = $36 ; tx/rx channel, $2b -> $3a valid

.org 0
rjmp start
.org int4addr
rjmp wakeupshit15
.org int5addr
rjmp clearirq
.org OVF2addr
rjmp wakeup


; shit15 data = pe4(int4)
; shit15 clock = pe0
; r0  shit15 temperature msb
; r1  shit15 temperature lsb
; r2  shit15 humidity
; r3  activity msb
; r4  activity lsb
; r5  buffer pointer temporary storage
; r6  light sensor msb
; r7  light sensor lsb
; r8  
; r9  
; r10 des_addr msb
; r11 des_addr lsb
; r12 
; r13 
; r14 
; r15 button press temporary register
; r16 interrupt temporary register
; r17 interrupt temporary register
; r18 rf unit state register
; r19 adc delay timer
; r20 timer register 1
; r21 no_ack counter
; r22 wakeup delay timer
; r23 button wait register
; r24 button press
; r25 previous button press (sent as button data)
; r26 wait timer for joinrequest
; r27
; ypointer is buffer end
; zl  
; zh  

start: ; configure microcontroller registers
; using internal 8MHz RC oscillator
; system clock set to 1MHZ by /8 prescaler in fuse bits
ldi r16,high(RAMEND)
out SPH,r16 ; Set Stack Pointer to top of RAM
ldi r16,low(RAMEND)
out SPL,r16
ldi r16,$17
out ddrb,r16 ; set ss,sclk,mosi,slp_tr as output
ldi r16,8
out portb,r16 ; enable pullup for miso
ldi r16,1
out spsr,r16 ; set up spi
ldi r16,$50
out spcr,r16 ; set up spi
sbi portb,portb0 ; set ss pin high
cbi portb,portb4 ; set slp_tr low
sbi ddra,dda7 ; set reset pin as output
sbi porta,porta7 ; pull reset high on rf unit
ldi r16,$0c
sts eicrb,r16 ; configure int5 for rising edge
ldi r16,$20
out eimsk,r16 ; enable int5
ldi r16,high(home_addr) ; set up des_addr to something in system for start
mov r10,r16
ldi r16,low(home_addr) ; set up des_addr
mov r11,r16
ldi yh,$02 ; initialize buffer pointer
ldi yl,$00
clr r18 ; initialize rf state register
clr r5 ; initialize pointer buffer
clr r25 ; initialize registers
clr r24
clr r23

;turn off watchdog timer
wdr ; reset wdt
ldi r16,$00 ; clear all resets
out mcusr,r16 ; turn off wdrf
ldi r16,$1e
sts wdtcsr,r16 ; enable writing of wdt
ldi r16,$06
sts wdtcsr,r16 ; turn off wdt, 1s timer

;setup power reduction registers
ldi r16,$ab
sts prr0,r16 ; turn off adc,usart0,t1,t0,twi
ldi r16,$3f
sts prr1,r16 ; turn off t5,t4,t3,usart3,usart2,usart1
ldi r16,$90
out acsr,r16 ; turn off comparator

;setup t2 as rtc at 1s interval wakeup
ldi r16,$20
sts assr,r16 ; set t2 to assynchronous mode
ldi r16,$05
sts tccr2b,r16 ; set t2 prescaler to /128 - 1s wakeup period

;make sure t2 is done rewriting itself
checkassr:

lds r16,assr
andi r16,$1f ; check assr(4:0) clear
brne checkassr

clr r16
sts tifr2,r16 ; clear all pending interrupts
ldi r16,$01
sts timsk2,r16 ; enable t2 overflow interrupt

;setup shit15 - pe0 is data, pe4 is clock
sbi ddre,dde0 ; set clock as output
cbi porte,porte4 ; make sure pullups are off for data
rcall shit15setup

;configure rf unit registers

;wait
ldi r20,$80 ; load the wait timer to 128 cycles (x10/ck)
rcall wait2 ; wait ~(1280/1MHz = 1.2ms) for rf unit to stabilize

;go to trx_off state
rcall txoff ; go to trx_off state on rf unit

;setup clkm
ldi r16,$c3 ; load first data byte - write trx_ctrl_0 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
clr r16 ; load second data byte - turn off clkm
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup short_addr_0
ldi r16,$e0 ; load first data byte - write short_addr_0 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,low(src_addr) ; load second data byte - src_addr lsb
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup short_addr_1
ldi r16,$e1 ; load first data byte - write short_addr_1 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,high(src_addr) ; load second data byte - src_addr msb
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup pan_id_0
ldi r16,$e2 ; load first data byte - write pan_id_0 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,low(pan_id) ; load second data byte - pan_id lsb
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup pan_id_1
ldi r16,$e3 ; load first data byte - write pan_id_1 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,high(pan_id) ; load second data byte - pan_id msb
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup phy_cc_ca - set channel id
ldi r16,$c8 ; load byte - write phy_cc_ca register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,channel ; load data byte - 
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup phy_tx_pwr - turn crc on
ldi r16,$c5 ; load byte - write phy_tx_pwr register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,$80 ; load data byte - auto_crc=on,pwr=+3dbm
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup xah_ctrl - set frame and csma retries
ldi r16,$ec ; load byte - write xah_ctrl register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,retries ; load data byte - frame and csma retries
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup csma_seed_1
ldi r16,$ee ; load byte - write csma_seed_1 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,high(csma_seed) ; load data byte - min_be=0,aack_set=0,i_am_coord=0,csma(10:8)
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;setup csma_seed_0
ldi r16,$ed ; load first data byte - write csma_seed_1 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,low(csma_seed) ; load data byte - csma(7:0)
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high

;clear pending irqs on rf unit 
ldi r16,$8f ; load first data byte - read register irq_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte and clear pending irqs
sbi portb,portb0 ; pull ss high

;enable irqs on rf unit
ldi r16,$ce ; load first data byte - write register irq_mask command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$08 ; load second data byte - trx_end only
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high

;clear pending irqs on micro
clr r16
out eifr,r16 ; clear any interrupt flags that are set

;enable interrupts on micro
sei ; turn on interrupts

;enter sleep mode on rf unit
sbi portb,portb4 ; pull slp_tr high to enter sleep mode
ldi r20,$80 ; load the wait timer to 128 cycles (x10/ck)
rcall wait2 ; wait ~(1280/1MHz = 1.2ms) to make sure were in sleep

repeat: ; transmit data from sleep mode
; use watchdog timer to eliminate lockups while not sleeping
cli ; turn off interrupts while enabling watchdog timer
wdr ; reset wdt
ldi r16,$1e
sts wdtcsr,r16 ; enable writing of wdt
ldi r16,$0e
sts wdtcsr,r16 ; turn on wdt, 1s timer
sei ; turn interrupts back on

rcall shit15temp ; read shit15 temperature

rcall shit15humidity ; read shit15 humidity

cbi portb,portb4 ; pull slp_tr low to exit sleep mode
ldi r20,$28 ; load wait timer to 40 cycles (x10/ck)
rcall wait2 ; wait ~(400/1MHZ = 400us) for rf unit clock to stabilize

rcall checktxoff ; check to see if rf unit is in tx_off state

rcall txonaret ; put the rf unit in tx_aret_on state

cpi r21,$0c ; check how long its been since ack (12min)
brlo shortout ; dont bother with data packets if longout
ldi yl,$00 ; clear old data
ldi r21,$0f ; keep ack counter from incrementing back to $00
rcall transmitrequest ; transmit join request
ldi r18,$02 ; set rf state to joinrequest sent
rjmp rfwait ; wait for transmit done

shortout: ; possibly still in system - keep full data transmits
 
rcall transmitpacket ; send data
ldi r18,$00 ; set rf state to data sent

rfwait: ; wait till transmission is complete - could be replaced with a sleep
;int5 can only be used as level interrupt to wake from most sleep modes
;int5 must be configured as rising edge as it is active high
;could use idle mode to sleep during this operation
;idle mode would save 0.7mA max - probably not worth it
nop
nop
nop
cpi r18,$40 ; check if all transmissions are done
breq sleepstate ; shut down if all transmissions done
cpi r18,$80 ; check if all transmission are done with backlog
breq backlog ; backlog data
cpi r18,$04 ; check if waiting for joinack
breq rfwait1 ; go to timeout sequence if waiting for joinack
rjmp rfwait ; else keep waiting


rfwait1: ; wait for joinack

ldi r26,$ff ; wait some sweet ass long time for joinack

wait3: ; 255x16/1MHz = 4ms waitloop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
cpi r18,$04 ; check if we have a new network
brne rfwait ; go back to waiting if new network
dec r26 ; check if done
brne wait3 ; keep going if not done

backlog: ; store backlogged data

cpi r21,$0c ; check if in long_out state
brsh sleepstate ; dont bother backlogging if long_out
st y+,r6 ; load data to buffer if failed
st y+,r7
st y+,r3
st y+,r4
st y+,r0
st y+,r1
st y+,r2
st y+,r25
inc r21 ; increment no_ack counter
cpi yh,$03 ; check if counter has overflowed
brlo sleepstate ; skip if not
ldi yh,$02 ; reset pointer if overflow
ldi yl,$00 ; reset pointer if overflow

sleepstate: ; finish off and go to sleep

rcall forcetxoff ; go to tx_off state so you can sleep
sbi portb,portb4 ; pull slp_tr high to enter sleep mode
ldi r16,$07
out smcr,r16 ; set to power-save mode and enable sleep mode
ldi r22,$3c ; set up repeat timer to 60cycles
; turn watchdog timer off when going back to sleep
cli ;  turn off interrupts while disabling watchdog timer
wdr ; reset wdt
in r16,mcusr ; get reset flag status
andi r16,$f7 ; mask off wdrf to 0
out mcusr,r16 ; turn off wdrf
ldi r16,$1e
sts wdtcsr,r16 ; enable writing of wdt
ldi r16,$06
sts wdtcsr,r16 ; turn off wdt, 1s timer
sei ; turn interrupts back on

sleepstate3:
sleep
nop
nop
nop

sleepstate2:
dec r22
brne sleepstate3 ; return to sleep if not yet 60s
clr r16
out smcr,r16 ; disable sleep mode
rjmp repeat ; take measurements and send them off

txoff: ; send trx_off command to rf unit and wait till stable

ldi r16,$c2 ; load first data byte - write register trx_state command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$08 ; load second data byte - data trx_off bit
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high

checktxoff: ; check current state to see if in tx_off state

ldi r16,$81 ; load first data byte - read register trx_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load second data byte - blank for reading
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
cpi r16,$08
brne checktxoff
ret ; return to previous duty

forcetxoff: ; send trx_off command to rf unit and wait till stable

ldi r16,$c2 ; load first data byte - write register trx_state command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$03 ; load second data byte - data force_trx_off bit
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high


checkforcetxoff: ; check current state to see if in tx_off state

nop ; delay for a bit to make sure the device is off
nop
nop
nop
ldi r16,$81 ; load first data byte - read register trx_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load second data byte - blank for reading
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
cpi r16,$08
brne forcetxoff ; redo if not off - only takes 1us to turn off (changed due to lock up bug of getting stuck in check loop)
ret ; return to previous duty

pllon: ; send pll_on command to rf unit

ldi r16,$c2 ; load first data byte - write register trx_state command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$09 ; load second data byte - data pll_on bit
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high

checkpllon: ; check current state to see if in pll_on state

ldi r16,$81 ; load first data byte - read register trx_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load second data byte - blank for reading
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
cpi r16,$09
brne checkpllon
ret ; return to previous duty

txonaret: ; send trx_aret_on command to rf unit and wait till stable

ldi r16,$c2 ; load first data byte - write register trx_state command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$19 ; load second data byte - data trx_aret_on bit
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high

checktxonaret: ; check current state to see if in tx_aret_on state

ldi r16,$81 ; load first data byte - read register trx_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load second data byte - blank for reading
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
cpi r16,$19
brne checktxonaret
ret ; return to previous duty

rxonaack: ; send rx_aack_on command to rf unit and wait till stable

ldi r16,$c2 ; load first data byte - write register trx_state command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$16 ; load second data byte - data rx_aack_on bit
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high

checkrxonaack: ; check current state to see if in rx_aack_on state

ldi r16,$81 ; load first data byte - read register trx_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load second data byte - blank for reading
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
cpi r16,$16
brne checkrxonaack
ret ; return to previous duty

spiwrite: ; read and write data over spi

out spdr,r16 ; write transmitted byte to spi

wait: ; read spi register to check when done

in r16,spsr
sbrs r16,spif
rjmp wait
in r16,spdr ; write recieved byte to spi register
ret ; return to previous duty

wait2: ; wait timer (~12 cylces per value in r20)

nop
nop
nop
nop
nop
nop
nop
nop
dec r20
brne wait2
ret ; return to previous duty

joinrecieve: ; get new des_addr

cpi r18,$04 ; check if waiting for joinack
brne done9 ; skip if not
ldi r16,$20 ; load data byte - read buffer command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - frame length byte
cpi r16,$0b ; check if its a join frame length
brne donejoinfail ; finish if not
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save fcf(7:0)
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save fcf(15:8)
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - seq (used as command byte)
cpi r16,$06 ; check if joinpacket
brne donejoinfail ; finish if not
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save des_panid(7:0)
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save des_panid(15:8)
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save des_addr(7:0)
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save des_addr(15:8)
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - src_addr(7:0)
mov r11,r16
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - src_addr(15:8)
mov r10,r16
; dont bother with the rest of the data - it doesnt matter
;ldi r16,$00 ; load data byte - blank for reading
;rcall spiwrite ; send byte - do not save fcs(7:0)
;ldi r16,$00 ; load data byte - blank for reading
;rcall spiwrite ; send byte - do not save fcs(15:8)
;ldi r16,$00 ; load data byte - blank for reading
;rcall spiwrite ; send byte - lqi
sbi portb,portb0 ; pull ss high
rcall checkrxonaack ; make sure we are no longer in rx_busy
rcall pllon ; go to pll_on state
rcall txonaret ; go to tx_on state
rcall transmitpacket ; send out data packet
ldi r18,$10 ; set state register to retry transmit
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

donejoinfail: ; finish and wait for next packet

sbi portb,portb0 ; pull ss high
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

done9: ; rx bad packet

ldi r18,$40 ; set rf state to done
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

clearirq: ; clear irq register and irq line

in r16,sreg ; get sreg
push r16 ; push sreg on stack
ldi r16,$8f ; load first data byte - read register irq_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high

checkrf: ; check rf unit state

ldi r16,$81 ; load first data byte - read register trx_status command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load second data byte - blank for reading
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
cpi r16,$16 ; check if in rx_on
breq joinrecieve ; go to get data
cpi r16,$11 ; check if in busy_rx
breq joinrecieve ; go to get data
cpi r16,$1f ; check if in state transition
breq checkrf ; keep checking till in a new state
cpi r16,$12 ; check if in busy_tx state
breq checkrf ; keep checking till in a new state
;else check successful transmit before switching back to sleep
ldi r16,$82 ; load data byte - read trx_state to get trac_status
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load data byte - blank byte for reading
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
andi r16,$e0 ; mask off trac_status
cpi r16,$60 ; check if success or data_pending success
brlo success ; skip if success
cpi r18,$00 ; check if last transmission was a data packet
breq retry ; get new des_addr
cpi r18,$10 ; check if last transmission was a retry packet
breq retryfail ; backlog and end
cpi r18,$20 ; check if last transmission was a backlog packet
breq backlogfail ; backlog and end
ldi r18,$40 ; else set to shutdown
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; return from interrupt

retry: ; get new des_addr and retransmit

rcall transmitrequest
ldi r18,$02 ; set joinrequest state bit
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

backlogfail: ; reset backlog pointer

mov yl,r5 ; reset data pointer because data didnt go out

retryfail: ; backlog and end

ldi r18,$80 ; set backlog flag
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

success: ; tx success

cpi r18,$00 ; check if last packet was data
breq checkback ; see if there is backlogged data
cpi r18,$02 ; check if last packet was join request
breq gotorx ; set to rx and wait for join ack
cpi r18,$20 ; check if last packet was backlog data
breq irqdone ; finish off
cpi r18,$10 ; check if last packet was retry
breq checkback ; check for backlogged data
rjmp done9 ; finish off if bad state

checkback: ; check for backlogged data

cpi yl,$00 ; check for backlogged data
breq irqdone ; finish if none
mov r5,yl ; store data pointer in case of failure
rcall transmitold ; transmit backlogged data
ldi r18,$20 ; set state to backlog-aack
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

irqdone: ; finish interrupt and return

clr r21 ; reset no_ack register
ldi r18,$40 ; set rf state to done
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

txdata: ; transmit a data packet

rcall transmitpacket ; send data
ldi r18,$00 ; set rf state to data sent
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; clear interrupt and return to previous duty

gotorx: ; recieve joinconfirm

rcall pllon ; go to pll_on state
rcall rxonaack ; go to rx_on_aack state
ldi r18,$04 ; set rf state to rx-waiting
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; return from interrupt

transmitbeacon: ; transmit a beacon frame

sbi portb,portb4 ; pull slp_tr high to begin transmit
nop ; delay to make sure the pin is high long enough
cbi portb,portb4 ; pull slp_tr low

ldi r16,$60 ; load data byte - write buffer command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$0b ; load data byte - frame length byte
rcall spiwrite ; send byte
ldi r16,$40 ; load data byte - fcf(7:0) - broadcast,no ack
rcall spiwrite ; send byte
ldi r16,$88 ; load data byte - fcf(15:8) - short address,pan_ids equal
rcall spiwrite ; send byte
ldi r16,$00 ; load data byte - seq(7:0) - command(beacon)
rcall spiwrite ; send byte
ldi r16,low(pan_id) ; load data byte - pan_id(7:0)
rcall spiwrite ; send byte
ldi r16,high(pan_id) ; load data byte - pan_id(15:8)
rcall spiwrite ; send byte
ldi r16,$ff ; load data byte - destination address (7:0) - broadcast
rcall spiwrite ; send byte
ldi r16,$ff ; load data byte - destination address (15:0) - broadcast
rcall spiwrite ; send byte
ldi r16,low(src_addr) ; load data byte - source address (7:0)
rcall spiwrite ; send byte
ldi r16,high(src_addr) ; load data byte - source address (15:8)
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
ret ; return to previous duty

wakeup: ; clear interrupts and return to previous task
nop
nop
nop
reti

;talk to shit15, only works for cpu clock <=2MHZ
;data pin can never be output high - leave pullup off
;needs external pullup resistor for proper operation
wakeupshit15: ; clear interrupts and return
nop
nop
nop
cbi eimsk,4 ; disable int4 as pe4 will still be low when returning
nop
reti


shit15setup: ; set the device to low res mode

rcall shit15reset ; reset the device in case its fuxxored
rcall startshit15 ; send start sequence

;data sequence - register write command $06
sbi porte,porte0 ; clock high - data bit one
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit two
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit three
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit four
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit five
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
sbi porte,porte0 ; clock high - data bit six
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit seven
cbi porte,porte0 ; clock low
sbi ddre,dde4 ; data low
sbi porte,porte0 ; clock high - data bit eight
cbi porte,porte0 ; clock low

rcall shit15ack0 ; wait for ack from shit15

;data sequence - register write data $01
sbi ddre,dde4 ; data low
sbi porte,porte0 ; clock high - data bit one
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit two
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit three
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit four
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit five
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit six
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit seven
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
sbi porte,porte0 ; clock high - data bit eight
cbi porte,porte0 ; clock low

rcall shit15ack0 ; wait for ack from shit15
ret ;done setting up the device

shit15temp: ; read temperature data from shit15
;send read temp commmand
rcall startshit15 ; send start sequence

;data sequence - read temperature command $03
sbi porte,porte0 ; clock high - data bit one
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit two
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit three
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit four
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit five
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit six
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
sbi porte,porte0 ; clock high - data bit seven
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit eight
cbi porte,porte0 ; clock low
;sbi ddre,dde4 ; data low - if last databyte is 1 - leave it high for ack

rcall shit15ack0 ; wait for ack from shit15

sbi eimsk,4 ; enable int4
ldi r16,$07
out smcr,r16 ; set to power-save mode and enable sleep mode
nop
nop
nop
sleep ; sleep while waiting for low level on pe4
nop
nop
nop
clr r16
out smcr,r16 ; disable sleep mode

rcall shit15read ; read out temperature data from shit15 (msb)
rcall shit15ack3 ; acknowledge reciept of bit
mov r0,r16 ; move msb to another register
rcall shit15read ; read out temperature data from shit15 (lsb)
rcall shit15ack4 ; end transmission ack
mov r1,r16 ;  move lsb to another register
ret ; continue with previous task

shit15humidity: ; read humidity data from shit15
;send read humidity command
rcall startshit15 ; send start sequence

;data sequence - read humidity command $05
sbi porte,porte0 ; clock high - data bit one
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit two
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit three
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit four
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit five
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
sbi porte,porte0 ; clock high - data bit six
cbi porte,porte0 ; clock low
sbi ddre,dde4 ; data low
sbi porte,porte0 ; clock high - data bit seven
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
sbi porte,porte0 ; clock high - data bit eight
cbi porte,porte0 ; clock low
;sbi ddre,dde4 ; data low - if last databyte is 1 - leave it high for ack

rcall shit15ack0 ; wait for acknowledge from shit15

sbi eimsk,4 ; enable int4
ldi r16,$07
out smcr,r16 ; set to power-save mode and enable sleep mode
nop
nop
nop
sleep ; sleep while waiting for low level on pe4
nop
nop
nop
clr r16
out smcr,r16 ; disable sleep mode

rcall shit15read ; read out humidity data from shit15 (msb)
rcall shit15ack3 ; acknowledge reciept of bit
rcall shit15read ; read out humidity data from shit15 (lsb)
rcall shit15ack4 ; end transmission ack
mov r2,r16 ;  move lsb to another register
ret ; return with previous task

shit15ack4: ; end transmission ack

sbi porte,porte0 ; clock high - ack
cbi porte,porte0 ; clock low
ret ; return to previous task

shit15ack3: ; data recipet acknowledge

sbi ddre,dde4 ; pull data low
sbi porte,porte0 ; clock high - ack
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; release data line
ret ; return to previous task

shit15read: ; read data from shit15

clr r16 ; clear the register where incoming data will be written
sbi porte,porte0 ; clock high - data bit one
sbic pine,pine4 ; check if data is low
sbr r16,$80 ; write data bit one to register
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit two
sbic pine,pine4 ; check if data is low
sbr r16,$40 ; write data bit two to register
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit three
sbic pine,pine4 ; check if data is low
sbr r16,$20 ; write data bit three to register
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit four
sbic pine,pine4 ; check if data is low
sbr r16,$10 ; write data bit four to register
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit five
sbic pine,pine4 ; check if data is low
sbr r16,$08 ; write data bit five to register
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit six
sbic pine,pine4 ; check if data is low
sbr r16,$04 ; write data bit six to register
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit seven
sbic pine,pine4 ; check if data is low
sbr r16,$02 ; write data bit seven to register
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high - data bit eight
sbic pine,pine4 ; check if data is low
sbr r16,$01 ; write data bit eight to register
cbi porte,porte0 ; clock low
ret ; return to previous activity

startshit15: ; start sequence

cbi ddre,dde4 ; set data high
cbi porte,porte0 ; make sure clock is low
sbi porte,porte0 ; pull clock high
sbi ddre,dde4 ; set data low
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi ddre,dde4 ; data high
cbi porte,porte0 ; clock low
sbi ddre,dde4 ; data low
ret ; return to previous task

shit15ack0: ; ack sequence for sending data

cbi ddre,dde4 ; release data line

shit15ack2: ; check that data line is low

sbic pine,pine4
rjmp shit15ack2
sbi porte,porte0 ; clock high - ack
cbi porte,porte0 ; clock low

shit15ack1: ; check that line has been released

sbis pine,pine4 ; check that line has been released
rjmp shit15ack1
ret ; return to previous task

shit15reset: ; reset sequence if it gets out of phase
;status register preserved
;must be followed by data start sequence
cbi ddre,dde4 ; data high
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
sbi porte,porte0 ; clock high
cbi porte,porte0 ; clock low
ret ; return to previous task

transmitrequest: ; transmit a request frame

sbi portb,portb4 ; pull slp_tr high to begin transmit
nop ; delay to make sure the pin is high long enough
cbi portb,portb4 ; pull slp_tr low

ldi r16,$60 ; load data byte - write buffer command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$0b ; load data byte - frame length byte
rcall spiwrite ; send byte
ldi r16,$40 ; load data byte - fcf(7:0) - broadcast,no ack
rcall spiwrite ; send byte
ldi r16,$88 ; load data byte - fcf(15:8) - short address,pan_ids equal
rcall spiwrite ; send byte
ldi r16,$01 ; load data byte - seq(7:0) - command(request)
rcall spiwrite ; send byte
ldi r16,low(pan_id) ; load data byte - pan_id(7:0)
rcall spiwrite ; send byte
ldi r16,high(pan_id) ; load data byte - pan_id(15:8)
rcall spiwrite ; send byte
ldi r16,$ff ; load data byte - destination address (7:0) - broadcast
rcall spiwrite ; send byte
ldi r16,$ff ; load data byte - destination address (15:0) - broadcast
rcall spiwrite ; send byte
ldi r16,low(src_addr) ; load data byte - source address (7:0)
rcall spiwrite ; send byte
ldi r16,high(src_addr) ; load data byte - source address (15:8)
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
ret ; return to previous duty

transmitold: ; transmit backlogged data

sbi portb,portb4 ; pull slp_tr high to begin transmit
nop ; delay to make sure the pin is high long enough
cbi portb,portb4 ; pull slp_tr low

ldi r16,$60 ; load data byte - write buffer command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
mov r17,yl ; load data byte - frame length byte
ldi r16,$0b ; increase frame length for header and crc
add r16,r17 ; increase frame length
rcall spiwrite ; send byte
ldi r16,$61 ; load data byte - fcf(data)
rcall spiwrite ; send byte
ldi r16,$88 ; load data byte - fcf
rcall spiwrite ; send byte
ldi r16,$04 ; load data byte - seq(backlogged data command)
rcall spiwrite ; send byte
ldi r16,low(pan_id) ; load data byte - des_panid
rcall spiwrite ; send byte
ldi r16,high(pan_id) ; load data byte - des_panid
rcall spiwrite ; send byte
mov r16,r11 ; load data byte - des_addr
rcall spiwrite ; send byte
mov r16,r10 ; load data byte - des_addr
rcall spiwrite ; send byte
ldi r16,low(src_addr) ; load data byte - src_addr
rcall spiwrite ; send byte
ldi r16,high(src_addr) ; load data byte - src_addr
rcall spiwrite ; send byte

dataload: ; load data to rf unit

ld r16,-y ; load data byte - data byte
rcall spiwrite ; send byte
cpi yl,$00 ; check if last byte
brne dataload ; branch if not last byte
sbi portb,portb0 ; pull ss high
ret ; return to previous duty


transmitpacket: ; transmit a packet

sbi portb,portb4 ; pull slp_tr high to begin transmit
nop ; delay to make sure the pin is high long enough
cbi portb,portb4 ; pull slp_tr low

ldi r16,$60 ; load data byte - write buffer command
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$13 ; load frame length byte - total bytes excluding this one, +2
rcall spiwrite ; send byte
ldi r16,$61 ; load fcf(7:0) byte - $61 for data packet
rcall spiwrite ; send byte
ldi r16,$88 ; load fcf(15:8) byte - $88 for data packet
rcall spiwrite ; send byte
ldi r16,$02 ; load sequence byte - command(data)
rcall spiwrite ; send byte
ldi r16,low(pan_id) ; load destination panid(7:0) byte
rcall spiwrite ; send byte
ldi r16,high(pan_id) ; load destination panid(15:8) byte
rcall spiwrite ; send byte
mov r16,r11 ; load destination address(7:0) byte
rcall spiwrite ; send byte
mov r16,r10 ; load destination address(15:8) byte
rcall spiwrite ; send byte
ldi r16,low(src_addr) ; load source address(7:0) byte
rcall spiwrite ; send byte
ldi r16,high(src_addr) ; load source address(15:8) byte
rcall spiwrite ; send byte
mov r16,r25 ; load data byte - button press
rcall spiwrite ; send byte
mov r16,r2 ; load data byte - humidity
rcall spiwrite ; send byte
mov r16,r1 ; load data byte - temperature0
rcall spiwrite ; send byte
mov r16,r0 ; load data byte - temperature1
rcall spiwrite ; send byte
mov r16,r4 ; load data byte - accelerometer lsb
rcall spiwrite ; send byte
mov r16,r3 ; load data byte - accelerometer msb
rcall spiwrite ; send byte
mov r16,r7 ; load data byte - light lsb
rcall spiwrite ; send byte
mov r16,r6 ; load data byte - light msb
rcall spiwrite ; send byte
sbi portb,portb0 ; pull ss high
ret ; return to previous duty




