Full Version : Thain PICIDE Routines V1.0 (PIC ASM)
avr >>PIC 8051 ZILOG ARM TI H8 ETC >>Thain PICIDE Routines V1.0 (PIC ASM)


AVR_Admin- 04-18-2006
CODE
NOLIST
; This file is part of picide, ATA(PI) interface to PIC18 family MCUs.
; Copyright (C) 2004-5 Toby Thain, toby@telegraphics.com.au

; This program is free software; you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by  
; the Free Software Foundation; either version 2 of the License, or
; (at your option) any later version.

; 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.

; You should have received a copy of the GNU General Public License  
; along with this program; if not, write to the Free Software
; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
LIST

TITLE picide
SUBTITLE "Utility routines"

;; Version history
;; 21-Oct-2004: 0.1 - started by Toby
;; 23-Feb-2005: 1.0 - public release under GPL

; contents of this module:
global udiv8_8 ; unsigned divide 8 bits by 8 bits
global udiv16_8 ; unsigned divide 16 bits by 8 bits
global udiv16_16; unsigned divide 16 bits by 16 bits
global udiv32_16; unsigned divide 32 bits by 16 bits
  global divd,divs; dividend & divisor, inputs to above routines
global hexdigit ; print W reg as ASCII hex digit
global puthex ; print W as two hex digits
global putdec ; print W as decimal digits
global putdec16 ; print 16 bit value in dec16 as decimal
  global dec16 ; input to above routine
  global decstr ; scratch space for above routine
global dumpsec ; print sector buffer in hex/ASCII, # lines in W
global dumpstuff; dump memory from FSR1 in hex/ASCII, # lines in W
global rnd8 ; quick and dirty LFSR (semi-random numbers)
  global LFSRVALUEL; LFSR state

#define UTIL_ASM
#include "defs.inc"

#define DUMPCOLS 16 ; controls format of hex dump routines

extern putch

udata_acs
divd res 4; dividend: 32 bits
divs res 2; divisor: 16 bits
dtemp res 2
divcnt res 1

temp res 1
rnd res 1
rndcnt res 1
decstr res 8
dec16 res 2; value used by putdec16
digcnt res 1
rowcnt res 1; used by dumpsec
colcnt res 2
dumpad res 2
ascii res DUMPCOLS+1
LFSRVALUEL res 1; used by rnd8
psltemp res 1; used by putstrbits,putstrlist

code

putdec: movwf divd
lfsr 0,decstr+7
clrf digcnt
decdig:   movlw 10
  rcall udiv8_8
  movff divd+1,POSTDEC0; remainder - store digits backwards
  incf digcnt
  tstfsz divd; quotient
    bra decdig ; no more digits
; output digits forwards
pdig:   movf PREINC0,w
  addlw '0'
  call putch
  decfsz digcnt
  bra pdig
return

putdec16:
lfsr 0,decstr+7
; set divisor
movlw 10
movwf divs
clrf divs+1
; set initial dividend
movff dec16,divd
movff dec16+1,divd+1
clrf digcnt
decdigb:  rcall udiv16_16
  movff divd+2,POSTDEC0; remainder - store digits backwards
  incf digcnt
 ; quotient becomes next dividend
  tstfsz divd
    bra decdigb
  tstfsz divd+1
    bra decdigb
; output digits forwards
pdigb:   movf PREINC0,w
  addlw '0'
  call putch
  decfsz digcnt
    bra pdig
return

puthex: movwf temp
swapf temp,w
rcall hexdigit
movf temp,w
hexdigit:
andlw 0x0f
addlw -10
bn isdec
  addlw 'A'-'0'-10
isdec: addlw '0'+10
goto putch

; print a hex/ASCII dump of the sector buffer
dumpsec:; # lines is in Wreg
lfsr 1,secbuf; set up read pointer
dumpstuff:; alternative entry with FSR1 pointing at data
movwf rowcnt
clrf dumpad; zero offset
clrf dumpad+1
dorow:; print hex offset at start of each line
movf dumpad+1,w
rcall puthex
movf dumpad,w
rcall puthex
_putchar ':'
lfsr 2, ascii; set up write pointer
movlw DUMPCOLS; # columns (bytes per line)
movwf colcnt
addwf dumpad; bump offset by bytes per line
bnc docol
  incf dumpad+1
docol:   movlw 0x7e
  cpfsgt INDF1
    bra sevenb; it's 7-bit, and not DEL
nonprint:   movlw '.'
    movwf POSTINC2
    bra dohex
sevenb:   movlw 0x1f
  cpfsgt INDF1
    bra nonprint; it's a control char
  movff INDF1,POSTINC2; it's ASCII, copy it over
dohex:   movf POSTINC1,w
  rcall puthex
  decfsz colcnt
    bra docol
_putchar ' '
; print ASCII row
clrf INDF2; add terminating NUL
_putstrd ascii
_crlf
decfsz rowcnt
  bra dorow
return

; helper routines used by macros in defs.inc
global putstrtail,putstrlist,putstrbits,psbit,putstrpc,psltemp

; print NUL-terminated string at TBLPTR
putstrtail:
putit:   tblrd *+
  movf TABLAT,w
  bz donestr
    call putch
    bra putit
donestr:return

; print NUL-terminated string at PC
putstrpc:
movff TOSU,TBLPTRU
movff TOSH,TBLPTRH
movff TOSL,TBLPTRL
putstr2:rcall putstrtail
; adjust return address to after end of string
fixuppc:btfsc TBLPTRL,0; is ptr odd?
  tblrd *+; yes, bump it by one
movf TBLPTRU,w; copy to return PC
movwf TOSU; ** cannot use movff **
movf TBLPTRH,w
movwf TOSH
movf TBLPTRL,w
movwf TOSL
return

; macro helper
; find indexed string in NUL-terminated list (at PC), print it
putstrlist:
movff TOSU,TBLPTRU
movff TOSH,TBLPTRH
movff TOSL,TBLPTRL
addlw 0; set flags on W
bz putstr2
skip:     tblrd *+
    movf TABLAT,f
    bnz skip
  decfsz WREG
    bra skip
print: bra putstr2; print the string pointed at

 IF 0; old version
putstrlist:
movf psltemp,w
isthis:   bz print
skip:     tblrd *+
    movf TABLAT,f
    bnz skip
  addlw -1
  bra isthis
print: bra putstrtail; print the string pointed at
 ENDIF

; macro helper
; print strings corresponding to bit vector, msb first
putstrbits:
movwf psltemp
movff TOSU,TBLPTRU
movff TOSH,TBLPTRH
movff TOSL,TBLPTRL
call psbit
bra fixuppc

psbit:   bcf STATUS,C
  rlcf psltemp,f
  bc printit; high bit was set
  btfsc STATUS,Z; nothing left?
    return
; skip to next string
skipbit:    tblrd *+
    movf TABLAT,f
    bnz skipbit
  bra psbit
printit:  rcall putstrtail
  bra psbit

 IF 0; old version
putstrbits:
movf psltemp,w
nextbit:bcf STATUS,C
rlcf psltemp
bc printit; high bit was set
btfsc STATUS,Z; nothing left to print
return
; skip to next string
skipbit:    tblrd *+
    movf TABLAT,f
    bnz skipbit
bra nextbit
printit:rcall putstrtail
bra nextbit
 ENDIF

; Galois LFSR
; from: http://www.piclist.com/techref/microchip/rand8bit.htm
; more info: http://www.shmoo.com/crypto/Cracking_DES/CH10/main.html
; seed LFSRVALUEL with a non zero value
rnd8: BCF     STATUS,C    
RRCF    LFSRVALUEL,W
BTFSC   STATUS,C
XORLW   0xB4; nice trick, sets the incoming MSB according to carry
MOVWF   LFSRVALUEL
return

; integer division
; based on code in Nova Programmer's Reference, p E-4
; on entry: divisor in W
;   dividend in divdhi,divdlo (16 bits)
; on exit: quotient in divdlo, remainder in divdhi
;   carry set if overflow
udiv8_8:
clrf divd+1; dividend is 8 bits only
udiv16_8:
movwf divs
subwf divd+1,w; dividend hi < divisor?
bc oflow; no - result won't fit in 8 bits
movlw 8 ; width of divisor
movwf divcnt
; carry is clear here
rlcf divd
dloop:   rlcf divd+1
  movf divs,w
  subwf divd+1,w
 ; carry is set if result zero or positive
  bnc next
    movwf divd+1; store subtracted result
next:   rlcf divd
  decfsz divcnt
    bra dloop
oflow: return

udiv16_16:; 16 bit dividend only
clrf divd+2
clrf divd+3
; divide 32 bit value by 16 bit value
; 16 bit quotient in divd1,0
; 16 bit remainder in divd2,3
udiv32_16:; OVERFLOW IS NOT CHECKED
movlw 16; width of divisor
movwf divcnt
bcf STATUS,C; clear carry here
rlcf divd
rlcf divd+1
loopb:   rlcf divd+2
  rlcf divd+3
 ; trial subtraction - divisor from high word of dividend
  movff divd+2,dtemp
  movf divs,w
  subwf dtemp
  movff divd+3,dtemp+1
  movf divs+1,w
  subwfb dtemp+1
 ; carry is set if result zero or positive
  bnc nextb
    movff dtemp,divd+2; store subtracted result
    movff dtemp+1,divd+3
nextb:   rlcf divd
  rlcf divd+1
  decfsz divcnt
    bra loopb
return

end



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.