$regfile = "attiny85.dat"
$crystal = 8000000
$hwstack = 32
$swstack = 4
$framesize = 24
'$reduceivr
'$noramclear
Config Clockdiv = 1
$projecttime = 52
Open "COMB.0:38400,8,n,1" For Output As #1 'TX-MOSI PIN5
Open "COMB.1:38400,8,n,1" For Input As #2 'RX-MISO PIN6
Const Maxwordbit = 5 'Z5 is maximum bit
Const Maxword =(2 ^ Maxwordbit) * 2
Const Maxwordshift = Maxwordbit + 1
'Dim the used variables
Dim Bstatus As Byte , Bretries As Byte , Bblock As Byte , Bblocklocal As Byte
Dim Bcsum1 As Byte , Bcsum2 As Byte , Buf(128) As Byte , Csum As Byte
Dim J As Byte , Spmcrval As Byte ' self program command byte value
Dim Z As Long 'this is the Z pointer word
Dim Vl As Byte , Vh As Byte ' these bytes are used for the data values
Dim Wrd As Word , Page As Word 'these vars contain the page and word address
Dim Bkind As Byte , Bstarted As Byte
'19pages x 64B=1216B |/2=608
Page = 19
Const _app = 608
'some constants used in serial com
Const Nak = &H15
Const Ack = &H06
'Const Can = &H18
$timeout = 1000000 'we use a timeout
Bretries = 5 'we try 5 times
Testfor123:
Bstatus = Waitkey(#2) 'wait for the loader to send a byte
Print #1 , Chr(bstatus);
If Bstatus = 123 Then 'did we received value 123 ?
Bkind = 0 'normal flash loader
Goto Loader
Elseif Bstatus <> 0 Then
Decr Bretries
If Bretries <> 0 Then Goto Testfor123 'we test again
End If
Goto _app 'goto the normal reset vector at address 0
'this is the loader routine. It is a Xmodem-checksum reception routine
Loader:
Do
Bstatus = Waitkey(#2)
Loop Until Bstatus = 0
If Bkind = 0 Then
Spmcrval = 3 : Gosub Do_spm ' erase the first page
Spmcrval = 17 : Gosub Do_spm ' re-enable page
End If
Bretries = 10 'number of retries
Do
Bblocklocal = 1
Bstarted = 0 ' we were not started yet
Csum = 0 'checksum is 0 when we start
Print #1 , Chr(nak); ' firt time send a nack
Do
Bstatus = Waitkey(#2) 'wait for statuse byte
Select Case Bstatus
Case 1: ' start of heading, PC is ready to send
Csum = 1 'checksum is 1
Bblock = Waitkey(#2) : Csum = Csum + Bblock 'get block
Bcsum1 = Waitkey(#2) : Csum = Csum + Bcsum1 'get checksum first byte
For J = 1 To 128 'get 128 bytes
Buf(j) = Waitkey(#2) : Csum = Csum + Buf(j)
Next
Bcsum2 = Waitkey(#2) 'get second checksum byte
If Bblocklocal = Bblock Then 'are the blocks the same?
If Bcsum2 = Csum Then 'is the checksum the same?
Gosub Writepage 'yes go write the page
Print #1 , Chr(ack); 'acknowledge
Incr Bblocklocal 'increase local block count
Else 'no match so send nak
Print #1 , Chr(nak);
End If
Else
Print #1 , Chr(nak); 'blocks do not match
End If
Case 4: ' end of transmission , file is transmitted
If Wrd > 0 And Bkind = 0 Then 'if there was something left in the page
Wrd = 0 'Z pointer needs wrd to be 0
Spmcrval = 5 : Gosub Do_spm 'write page
Spmcrval = 17 : Gosub Do_spm ' re-enable page
End If
' Waitms 100 ' OPTIONAL REMARK THIS IF THE DTR SIGNAL ARRIVES TO EARLY
Print #1 , Chr(ack); ' send ack and ready
Waitms 20
Goto _app ' start new program
Case &H18: ' PC aborts transmission
Goto _app ' ready
Case 123 : Exit Do 'was probably still in the buffer
Case Else
Exit Do ' no valid data
End Select
Loop
If Bretries > 0 Then 'attempte left?
Waitms 1000
Decr Bretries 'decrease attempts
Else
Goto _app 'reset chip
End If
Loop
'write one or more pages
Writepage:
If Bkind = 0 Then
For J = 1 To 128 Step 2 'we write 2 bytes into a page
Vl = Buf(j) : Vh = Buf(j + 1) 'get Low and High bytes
!lds r0, {vl} 'store them into r0 and r1 registers
!lds r1, {vh}
Spmcrval = 1 : Gosub Do_spm 'write value into page at word address
Wrd = Wrd + 2 ' word address increases with 2 because LS bit of Z is not used
If Wrd = Maxword Then ' page is full
Wrd = 0 'Z pointer needs wrd to be 0
Spmcrval = 5 : Gosub Do_spm 'write page
Spmcrval = 17 : Gosub Do_spm ' re-enable page
Page = Page + 1 'next page
Spmcrval = 3 : Gosub Do_spm ' erase next page
Spmcrval = 17 : Gosub Do_spm ' re-enable page
End If
Next
End If
Return
Do_spm:
Bitwait Spmcsr.0 , Reset ' check for previous SPM complete
Z = Page 'make equal to page
Shift Z , Left , Maxwordshift 'shift to proper place
Z = Z + Wrd 'add word
!lds r30,{Z}
!lds r31,{Z+1}
Spmcsr = Spmcrval 'assign register
!spm 'this is an asm instruction
Nop
Nop
Return
|