;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; pins
;;

constants
 [[pinb $23][ddrb $24][portb $25]
  [pinc $26][ddrc $27][portc $28]
  [pind $29][ddrd $2a][portd $2b]]

to pin-init
bsetb ddrd mosi + sck
bclrb portc mosi + sck
bsetb ddrc reset
bclrb portc reset
end

to powerup
end

define wait [millis][mwait :millis]
define random [from to][output :from + random1 :to - :from + 1]
define ignore [n][]

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; command handler
;;
constants [[buffer $300]]

to runcmd
let [cmd readb buffer]
if :cmd = 1 [enter-isp-mode]
if :cmd = 2 [exit-isp-mode]
if :cmd = 3 [chip-erase]
if :cmd = 4 [write-page-cmd]
if :cmd = 5 [read-cmd]
if :cmd = 6 [read-fuses]
if :cmd = 7 [write-fuses]
waituntil [poll-rdy]
end

to write-page-cmd
let [dst read buffer + 1
     src buffer + 3]
repeat 32
 [writef :dst read :src
  make "dst :dst + 1
  make "src :src + 2]
write-page :dst - 32
end

to read-cmd
let [src read buffer + 1
     len readb buffer + 3
     dst buffer]
repeat :len
 [write :dst readf :src
  make "dst :dst + 2
  make "src :src + 1]
end

to read-fuses
writeb buffer read-fusel
writeb buffer + 1 read-fuseh
writeb buffer + 2 read-fusee
end

to write-fuses
write-fusel readb buffer + 1 wait 50
write-fuseh readb buffer + 2 wait 50
write-fusee readb buffer + 3 wait 50
end

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; spi
;;

constants
 [[mosi 4][miso 8][sck $10]	;portd
  [reset $20]]								;portc

to pulse-reset
bclrb portc reset wait 3
bsetb portc reset wait 3
bclrb portc reset wait 3
end

to enter-isp-mode
pulse-reset
wait 20
at-cmd $ac $53 0 0
end

to exit-isp-mode
bsetb portc reset 
end

to at-read :a :b :c 
ignore spi-byte :a
ignore spi-byte :b
ignore spi-byte :c
output spi-byte 0
end

to at-cmd :a :b :c :d
ignore spi-byte :a
ignore spi-byte :b
ignore spi-byte :c
ignore spi-byte :d
end

to spi-byte :n
let [mask $80 res 0]
repeat 8
 [ifelse :n and :mask [bsetb portd mosi][bclrb portd mosi]
  bsetb portd sck
  make "res lsh :res 1
  make "res :res + btstb pind miso
  bclrb portd sck
  make "mask lsh :mask -1]
bclrb portd mosi
output :res
end

define chip-erase [][at-cmd $ac $80 0 0]
define poll-rdy [][output ((at-read $f0 0 0) and 1) = 0]

define readf [addr][output (readfl :addr) + (lsh readfh :addr 8)]
define readfl [addr][output at-read $20 byte1 :addr byte0 :addr]
define readfh [addr][output at-read $28 byte1 :addr byte0 :addr]

define writef [addr data][writefl :addr byte0 :data writefh :addr byte1 :data] 
define writefl [addr data][at-cmd $40 byte1 :addr byte0 :addr :data]
define writefh [addr data][at-cmd $48 byte1 :addr byte0 :addr :data]
define write-page [addr][at-cmd $4c byte1 :addr byte0 :addr 0]

define read-sig [n][output at-read $30 0 :n]

define read-fusel [][output at-read $50 0 0]
define read-fuseh [][output at-read $58 8 0]
define read-fusee [][output at-read $50 8 0]

define write-fusel [n][at-cmd $ac $a0 0 :n]
define write-fuseh [n][at-cmd $ac $a8 0 :n]
define write-fusee [n][at-cmd $ac $a4 0 :n]

