.include "m1281def.inc"

; increment of 4 for src_addr
; csma_seed = 8 x src_addr
.equ src_addr = $aaff ; 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
.org ADCCaddr
rjmp wakeupadc
.org URXC1addr ; USART1 - Rx Complete
rjmp wakeuprx
.org OC4Aaddr
rjmp timer4int

; lightsensor = pf0(adc0)
; shit15 data = pe4(int4)
; shit15 clock = pe0
; activity sensor = pd7(t0)
; xport = pd2,pd3(usart1),
; r0  frame length temporary register - write
; r1  frame length temporary register - read
; r2  adc msb temporary register
; r3  shit15 msb temporary register
; r4  shit15 lsb temporary register
; r5  adc lsb temporary register
; r6  joinrequest buffer index lsb
; r7  joinrequest buffer index msb
; r8  activity level temporary register
; r9  ed_level temporary register
; r10 usart temporary register
; r11 last rf tx packet length temporary register
; r12 shit15 humidity temporary register
; r13
; r14 
; r15 usart tx temporary register
; r16 temporary swap register for interrupts
; r17 temporary swap register for interrupts
; r18 temporary swap register for main
; r19 temporary swap register for main
; r20 wait loop register
; r21 wait loop register
; r22 hextoascii temporary register
; r23 usart rx temporary register
; r24 wakeup counter
; r25 transmit temporary register
; xregister is recieve buffer (r27(xh),r26(xl))
; yregister is buffer start (r29(yh),r28(yl))
; zregister is buffer end (r31(zh),r30(zl))
; data buffer set at 1k
; tregister is shit15 humidity/temperature irq differentiator
; joinrequest buffer is 256byte
; recieve buffer is 256byte

start: ; configure microcontroller registers
; using external oscillator (from RF unit)
; start up time 6CK + 65ms
; set to 1MHz initially, changed to 8MHz by clkm setup
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 - mode0, ck/2
ldi r16,$50
out spcr,r16 ; set up spi - mode0, ck/2 (4MHz)
sbi portb,portb0 ; set ss pin high
cbi portb,portb4 ; set slp_tr low
sbi porta,porta7 ; pull reset high on rf unit
sbi ddra,dda7 ; set reset pin as output
ldi r16,$0c
sts eicrb,r16 ; configure int5 for rising edge
ldi r16,$20
out eimsk,r16 ; enable int5
clr zl ; set buffer end to beginning of sram
clr yl ; set buffer start to beginning of sram
ldi zh,$02 ; set buffer end to beginning of sram
ldi yh,$02 ; set buffer start to beginning of sram
ldi xh,$05 ; set recieve buffer to middle of sram
clr xl ; set recieve buffer to middle of sram
ldi r23,$ff ; initialize receieve buffer count
ldi r24,$04 ; set wakeup counter to 32s

;wait for rf unit to stabilize
ldi r21,$04 ; load the wait timer to 3 cycles (x3084/ck)
rcall waitloop1 ; wait ~(9252/8MHz = 1.2ms) for rf unit to stabilize

;setup clkm
ldi r16,$c3 ; load first data byte - write trx_ctrl_0 register
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send data
ldi r16,$04 ; load second data byte - lowest driver strength, clkm = 8MHz
rcall spiwrite ; send data
sbi portb,portb0 ; pull ss high
nop ; idle for a bit as clock changes
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
nop
ldi r21,$ff ; load wait timer to 255 cycles (x3084/ck)
rcall waitloop1 ; wait ~100ms to make sure clock is stable

;setup analog inputs
ldi r16,$01
sts didr0,r16 ; turn off input stage for adc0 pin
ldi r16,$c0
sts admux,r16 ; use internal 2.56v as voltage reference,sample adc0

;setup t0 as activity counter
ldi r16,$06
out tccr0b,r16 ; set t0 to external clock on t0 falling edge

;setup t2 as rtc at 8s interval wakeup
ldi r16,$20
sts assr,r16 ; set t2 to assynchronous mode
ldi r16,$07
sts tccr2b,r16 ; set t2 prescaler to /1024 - 8s 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
out tifr2,r16 ; clear all pending interrupts
ldi r16,$01
sts timsk2,r16 ; enable t2 overflow interrupt

;setup t4 as usart recieve counter
ldi r16,$00
sts ocr4ah,r16 ; set counter top to 2ms
ldi r16,$10
sts ocr4al,r16 ; set counter top to 2ms

;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

;setup usart1
ldi r16,$98
sts ucsr1b,r16 ; enable rx,tx,rx interrupt
ldi r16,$0c
sts ubrr1l,r16 ; set baud rate to 38.4k

;configure rf unit registers

;go to trx_off state
rcall txoff ; go to trx_off state on rf unit

;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

;enable irqs
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 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

;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

rcall rxonaack ; put the rf unit in rx_aack_on state

repeat: ; handle backlogged data

cpse zh,yh ; check if buffer has data
rjmp handle ; go to data handler
cpse zl,yl ; check if buffer has data
rjmp handle ; go to data handler
rjmp repeat ; keep checking for data

handle: ; deal with data
; needs fixing to deal with buffer overruns

senddatausart: ; send data over usart from buffer

ldi r18,$ff ; move header byte to transmit buffer
rcall txusart
ld r18,z+ ; get data frame length from buffer
mov r1,r18 ; move frame lenghth to temporary register
rcall txusart

senddatausart1: ; send data over usart from buffer

ld r18,z+ ; get data from buffer
rcall txusart
dec r1
brne senddatausart1
ldi r18,low(src_addr)
rcall txusart
ldi r18,high(src_addr)
rcall txusart
ldi r18,$fe
rcall txusart
ldi r18,$fd
rcall txusart
sbrc zh,2 ; check if buffer at 1k
ldi zh,$02 ; reset buffer pointer to bottom of buffer
rjmp repeat ; get next byte from buffer

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

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

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

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

rxreadinterrupt: ; empty rx buffer while in interrupt

;ed_level is taken first because it is only valid for 224us after interrupt fires
ldi r16,$87 ; load data byte - read ed_level
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load data byte - blank byte for reading
rcall spiwrite ; send byte
mov r9,r16 ; move ed_level to temporary buffer
sbi portb,portb0 ; pull ss high

;get data from recieve buffer
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
subi r16,$06 ; decrease frame length for bits to be removed
st y+,r16 ; move frame length to buffer
subi r16,$03 ; decrease frame length for buffer fitting
mov r0,r16 ; move frame length to temporary register
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)
st y+,r16
dec r16 ; check if command byte is $01
brne notrequest1 ; skip if not $01

notrequest1: ; continue with data loading

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)

getdatarf1: ; keep loading data till frame compelete

ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte
st y+,r16 ; move byte to buffer
dec r0 ; decrement frame length byte
brne getdatarf1 ; keep decrementing until done
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
st y+,r16 ; move lqi to buffer
st y+,r9 ; move ed_level to buffer
sbrc yh,2 ; check if buffer at 1k
ldi yh,$02 ; reset buffer pointer to bottom of buffer
ret ; done writing data

transmit: ; transmit a packet

rcall checkrxonaack ; check to see if not in rx_busy state
rcall pllon ; go to pll on state
;check if there is data pending in rx buffer
ldi r16,$8f ; load first data byte - read register irq_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
sbrc r16,3 ; check if trx_end interrupt flag is set
rcall rxreadinterrupt ; empty rx buffer
rcall txonaret ; put the rf unit in tx_aret_on state

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
ld r16,x+ ; load data byte - frame length byte
mov r25,r16 ; load frame length byte to byte counter
ldi r17,$08 ; increase frame length for crc,panid,fcf,src_addr
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
ld r16,x+ ; load data byte - seq(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
ld r16,x+ ; load data byte - des_addr
rcall spiwrite ; send byte
ld r16,x+ ; 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
subi r25,$03 ; decrease byte counter for fixed transmit bytes
breq loaddone ; finish if no more bytes

dataload: ; load data to rf unit

ld r16,x+ ; load data byte - data byte
rcall spiwrite ; send byte
dec r25 ; check byte in sequence
brne dataload ; branch if not last byte

loaddone: ; finish data transmission and return

sbi portb,portb0 ; pull ss high
ret ; return to previous duty

waitloop1: ; wait timer (~3084 cycles per value in r21)

ser r20
rcall wait2
nop
nop
nop
nop
nop
nop
nop
nop
dec r21
brne waitloop1
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

gotorx: ; return to rx_on_aack state

;check successful transmit before switching back to rx
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 gotorx1 ; skip if success

;get data from rf unit tx buffer
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 -  old frame length byte - do not save
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte -  new frame length byte
subi r16,$08 ; decrease frame length for bits to be removed
st y+,r16 ; move frame length to buffer
mov r17,r16 ; move frame length to temporary register
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)
st y+,r16
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 - save des_addr(7:0)
st y+,r16
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - save des_addr(15:8)
st y+,r16
subi r17,$03 ; decrease frame length for buffer fitting
breq done7 ; finish if last byte
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save src_addr(7:0)
ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte - do not save src_addr(15:8)

getdatarf2: ; keep loading data till frame compelete

ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte
st y+,r16 ; move byte to buffer
dec r17 ; decrement frame length byte
brne getdatarf2 ; keep decrementing until done

done7: ; finish data storage

sbi portb,portb0 ; pull ss high
sbrc yh,2 ; check if buffer at 1k
ldi yh,$02 ; reset buffer pointer to bottom of buffer

gotorx1: ; turn on rx_on_aack state

rcall pllon ; go to pll_on state
rcall rxonaack ; go to rx_on_aack state
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; return to previous task

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 to clear interrupt
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 datacollect ; get data
cpi r16,$11 ; check if in busy_rx
breq datacollect ; 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
rjmp gotorx ; else put rf unit in rx_on_aack state

;removed checkcrc because crc is automatically checked with rx_aack

datacollect: ; get data from rf unit
;ed_level is taken first because it is only valid for 224us after interrupt fires
ldi r16,$87 ; load data byte - read ed_level
cbi portb,portb0 ; pull ss low
rcall spiwrite ; send byte
ldi r16,$00 ; load data byte - blank byte for reading
rcall spiwrite ; send byte
mov r9,r16 ; move ed_level to temprorary buffer
sbi portb,portb0 ; pull ss high

;get data from recieve buffer
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
subi r16,$06 ; decrease frame length for bits to be removed
st y+,r16 ; move frame length to buffer
mov r17,r16 ; move frame length to temporary register for joinrequest check
subi r16,$03 ; decrease frame length for buffer fitting
mov r0,r16 ; load frame length to byte counter
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)
st y+,r16
cpi r16,$01 ; check if command byte is $01 (joinrequest)
breq rxrequest ; go to joinrequest if $01

notrequest: ; continue with normal operation

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)

getdatarf: ; keep loading data till frame compelete

ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte
st y+,r16 ; move byte to buffer
dec r0 ; decrement frame length byte
brne getdatarf ; keep decrementing until done
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
st y+,r16 ; move lqi to buffer
st y+,r9 ; move ed_level to buffer
sbrc yh,2 ; check if buffer at 1k
ldi yh,$02 ; reset buffer pointer to bottom of buffer
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; done writing data

rxrequest: ; perform joinrequest storage

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)

getdatarf3: ; keep loading data till frame compelete

ldi r16,$00 ; load data byte - blank for reading
rcall spiwrite ; send byte
st y+,r16 ; move byte to buffer
dec r0 ; decrement frame length byte
brne getdatarf3 ; keep decrementing until done
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
st y+,r16 ; move lqi to buffer
st y+,r9 ; move ed_level to buffer
; transmit data out
rcall checkrxonaack ; check to see if not in rx_busy state
rcall pllon ; go to pll on state
rcall txonaret ; put the rf unit in tx_aret_on state

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

sbiw yh:yl,$04 ; reset data buffer to begining of join request
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,$61 ; load data byte - fcf(data)
rcall spiwrite ; send byte
ldi r16,$88 ; load data byte - fcf
rcall spiwrite ; send byte
ldi r16,$06 ; load join confirm 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
ld r16,y+ ; load data byte - des_addr
rcall spiwrite ; send byte
ld r16,y+ ; 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
sbi portb,portb0 ; pull ss high
adiw yh:yl,$02 ; reset pointer
sbrc yh,2 ; check if buffer at 1k
ldi yh,$02 ; reset buffer pointer to bottom of buffer
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; done writing data

txusart: ; transmit a byte via usart1 for main

lds r10,ucsr1a
sbrs r10,UDRE1
rjmp txusart
sts udr1,r18 ; send out data
ret ; go back to previous task

timer4int: ; reset usart timer due to bad packet

ldi r16,$08 ; turn off timer
sts tccr4b,r16 ; turn off timer
ldi r16,$00
sts timsk4,r16 ; disable t4 interrupts
ldi r23,$ff ; reset usart byte counter
ldi xl,$00 ;  reset buffer to bottom
reti ; return from interrupt

wakeup: ; take data every 32s

in r16,sreg ; get sreg
push r16 ;  push sreg on stack
dec r24 ; decrement wakeup counter
breq t0read ; take data if 32s
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti

t0read: ; get activity level from t0

in r8,tcnt0 ; move activity to temporary register
clr r16 ; reset activity level counter
out tcnt0,r16
rcall shit15temp ; initiate shit15 read - humidity included
ldi r16,$df ; take measurement from adc0
sts adcsra,r16 ; turn on adc,clear interrupt flag,enable interrupt,set to /128 (62.5kHz)
ldi r24,$04 ; reset wakeup counter to 32s
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti

wakeupadc: ; wakeup and return to previous task

in r16,sreg ; get sreg
push r16 ;  push sreg on stack
lds r5,adcl ; load lsb to r5
lds r2,adch ; load msb to r2
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti

shit15setup: ; set the device to low res mode
;talk to shit15, only works for cpu clock <=2MHZ
;code modded with nops to operate at 8MHz
;data pin can never be output high - leave pullup off
;needs external pullup resistor for proper operation
;sleep operation disabled for this application
;always read temperature before humidity

rcall shit15reset ; reset the device in case its fuxxored
rcall startshit15 ; send start sequence

;data sequence - register write command $06
;nops added to keep clock at 1MHz
sbi porte,porte0 ; clock high - data bit one
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit two
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit three
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit four
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit five
nop
nop
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
nop ; data takes time to rise and needs setup time
nop
nop
nop
nop
nop
sbi porte,porte0 ; clock high - data bit six
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit seven
nop
nop
cbi porte,porte0 ; clock low
sbi ddre,dde4 ; data low
sbi porte,porte0 ; clock high - data bit eight
nop
nop
cbi porte,porte0 ; clock low

rcall shit15ack0 ; wait for ack from shit15

;data sequence - register write data $01
;nops added to keep clock at 1MHz
sbi ddre,dde4 ; data low
sbi porte,porte0 ; clock high - data bit one
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit two
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit three
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit four
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit five
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit six
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit seven
nop
nop
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
nop ; data takes time to rise and needs setup time
nop
nop
nop
nop
nop
sbi porte,porte0 ; clock high - data bit eight
nop
nop
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
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit two
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit three
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit four
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit five
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit six
nop
nop
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
nop ; data takes time to rise and needs setup time
nop
nop
nop
nop
nop
sbi porte,porte0 ; clock high - data bit seven
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit eight
nop
nop
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
ret ; return to previous task and wait for shit15 to be done

wakeupshit15: ; collect data from shit15
in r17,sreg ; get sreg
push r17 ; push sreg on stack
brts shit15humread ; skip if its a humidity read
cbi eimsk,4 ; disable int4 as pe4 will still be low when returning
rcall shit15read ; read out temperature data from shit15 (msb)
rcall shit15ack3 ; acknowledge reciept of bit
mov r3,r16 ; move msb to another register
rcall shit15read ; read out temperature data from shit15 (lsb)
rcall shit15ack4 ; end transmission ack
mov r4,r16 ;  move lsb to another register
rcall shit15humidity
pop r17 ; get off stack
out sreg,r17 ; return sreg
set ; set tregister to indicate humidity request in progress
reti ; continue with previous task

shit15humread: ; read out humidity data from shit 15
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 r12,r16 ; move humidity data to temporary register
ldi r16,$07 ; load frame length
st y+,r16 ; move frame length to buffer
ldi r16,$03 ; set command byte to data from stationary nodes
st y+,r16 ; move frame type to buffer
st y+,r5 ; move adc lsb to buffer
st y+,r2 ; move adc msb to buffer
st y+,r4 ; move shit15 temperature lsb to buffer
st y+,r3 ; move shit15 temperature msb to buffer
st y+,r12 ; move shit15 humidity to buffer
st y+,r8 ; move activity level to buffer
sbrc yh,2 ; check if buffer at 1k
ldi yh,$02 ; reset buffer pointer to bottom of buffer
pop r17 ; get off stack
out sreg,r17 ; return sreg
clt ; reset to temperature read
reti ; return with previous task

shit15humidity: ; read humidity data from shit15
;send read humidity command
rcall startshit15 ; send start sequence

;data sequence - read humidity command $05
;nops added to keep clock at 1MHz
sbi porte,porte0 ; clock high - data bit one
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit two
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit three
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit four
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high - data bit five
nop
nop
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
nop ; data takes time to rise and needs setup time
nop
nop
nop
nop
nop
sbi porte,porte0 ; clock high - data bit six
nop
nop
cbi porte,porte0 ; clock low
sbi ddre,dde4 ; data low
sbi porte,porte0 ; clock high - data bit seven
nop
nop
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; data high
nop ; data takes time to rise and needs setup time
nop
nop
nop
nop
nop
sbi porte,porte0 ; clock high - data bit eight
nop
nop
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
ret ; return to previous task and wait for shit15 to take data

shit15ack4: ; end transmission ack
;nops added to keep clock at 1MHz
sbi porte,porte0 ; clock high - ack
nop
nop
cbi porte,porte0 ; clock low
ret ; return to previous task

shit15ack3: ; data recipet acknowledge
;nops added to keep clock at 1MHz
sbi ddre,dde4 ; pull data low
sbi porte,porte0 ; clock high - ack
nop
nop
cbi porte,porte0 ; clock low
cbi ddre,dde4 ; release data line
ret ; return to previous task

shit15read: ; read data from shit15
;nops added to keep clock at 1MHz and meet data valid time of 250ns
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
nop
nop
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
nop
nop
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
nop
nop
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
nop
nop
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
nop
nop
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
nop
nop
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
nop
nop
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
;nops added to keep clock at 1MHz
cbi ddre,dde4 ; set data high
cbi porte,porte0 ; make sure clock is low
nop
nop
sbi porte,porte0 ; pull clock high
sbi ddre,dde4 ; set data low
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
cbi ddre,dde4 ; data high
nop ; data takes time to rise and needs setup time
nop
nop
nop
nop
nop
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
;nops added to keep clock at 1MHz
sbic pine,pine4
rjmp shit15ack2
sbi porte,porte0 ; clock high - ack
nop
nop
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
;nops added to slow it down to 1MHz
cbi ddre,dde4 ; data high
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
nop
nop
sbi porte,porte0 ; clock high
nop
nop
cbi porte,porte0 ; clock low
ret ; return to previous task

wakeuprx: ; process incoming bytes on usart1

in r16,sreg ; get sreg
push r16 ;  push sreg on stack
ldi r16,$00
sts tcnt4h,r16 ; set counter to zero
sts tcnt4l,r16 ; set counter to zero
lds r16,udr1 ; load recieved byte
;subi r16,$20 ; test code to make ascii work
;lsl r16 ; test code to make ascii work
cpi r23,$ff ; check to see if you already have the header byte
brne usartrx ; go to data recieve

rxheadercheck: ; check for header byte

;cpi r16,$a0 ; check if header byte - testcode to make ascii work
cpi r16,$ff ; check if header byte - $ff
brne done5 ; skip if not
ldi r16,$2f ; set up byte timeout counter
out tifr4,r16 ; clear all t4 interrupt flags
ldi r16,$02
sts timsk4,r16 ; turn on t4 interrupt
ldi r16,$0d
sts tccr4b,r16 ; turn on counter, set to 128us period
clr r23 ; set byte number register to 0

done5:
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; return to previous task

usartrx: ; recieve data

tst r23 ; check for first byte
brne usartrxdata; skip if not first byte
clr xl ; reset buffer to bottom
st x+,r16 ; store recieved byte
mov r23,r16 ; move frame length to byte number
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; return to previous task

usartrxdata: ; load data bytes

st x+,r16 ; store recieved byte
dec r23 ; check for last byte
brne done5 ; continue
ldi xl,$00 ; go to bottom of buffer
ld r16,x+ ; load frame length byte
cpi r16,$03 ; check if there are at least three bytes
brlo done6 ; throw away the packet if its invalid
cpi r16,$40 ; check if there are more than 64 bytes
brsh done6 ; dont transmit if too big
ld r16,x ; load command byte
cpi r16,$08 ; check if a transmit packet
brne done6 ; skip if not a transmit packet
ldi xl,$00 ; reset to packet length byte
rcall transmit ; transmit from buffer if valid

done6: ; reset counter and return to previous task

ldi r16,$08 ; turn off timeout counter
sts tccr4b,r16 ; turn off timeout counter
ldi r16,$00
sts timsk4,r16 ; disable t4 interrupts
ldi r23,$ff ; set byte number to $ff to reset count
pop r16 ; get off stack
out sreg,r16 ; return sreg
reti ; return to previous task



