CON _XTALFREQ = 20_000_000 'PLL stage 0: crystal frequency _XDIV = 2 'PLL stage 1: crystal divider _XMUL = 1 'PLL stage 2: crystal / div * mul _XDIVP = 1 'PLL stage 3: crystal / div * mul / divp (1,2,4..30) _XOSC = %01 'OSC ' %00=OFF, %01=OSC, %10=15pF, %11=30pF _XSEL = %11 'XI+PLL ' %00=rcfast(20+MHz), %01=rcslow(~20KHz), %10=XI(5ms), %11=XI+PLL(10ms) _XPPPP = ((_XDIVP>>1) + 15) & $F ' 1->15, 2->0, 4->1, 6->2...30->14 _SETFREQ = 1<<24 + (_XDIV-1)<<18 + (_XMUL-1)<<8 + _XPPPP<<4 + _XOSC<<2 _ENAFREQ = _SETFREQ + _XSEL ' %0000_000e_dddddd_mmmmmmmmmm_pppp_cc_ss ' enable oscillator 'Serial functions for data logging rx_pin = 63 tx_pin = 62 baud_rate = 115_200 clock_freq = _XTALFREQ / _XDIV * _XMUL / _XDIVP asynconfig = (clock_freq * 4 / (baud_rate / 16))<<10 | 7 'bitrate format is 16.6<<10, 8N1 framing 'calc limited to below clock_freq of 512 MHz DAT 'not Spin code ORGH 0 'loaded to hubram at address 0 ORG 'longword addressing at 0 '******************************************************************************* ' COG Variables (Auto-copied to cogram on COGINIT #%0x_xxxx,#0 after program load) '******************************************************************************* count jmp #_diaginit sec long clock_freq pin bits res 1 pincfg tickstart res 1 bcdi temp1 res 1 bcdlen res 1 bcdstr temp2 res 1 a1 res 1 a3 res 1 b1 res 1 a64 res 1 a64h res 1 r64 res 1 r64h res 1 FIT '******************************************************************************* ' HUB Code '******************************************************************************* ORGH $400 ALIGNL _main mov pincfg, ##(%0100<<28) 'select OUT as input source loc pa, #\@diag11 call #allpins mov pincfg, #0 'disable I/O clocking (unregistered I/O) loc pa, #\@diag12 call #allpins mov pincfg, ##(%100<<14) 'enable I/O clocking (registered I/O) loc pa, #\@diag13 call #allpins jmp #$ allpins call #puts mov count, #0 .count mov pb, count add pb, #"0" call #putch call #putsp mov pin, #61 'pins 55-57 are pushbuttons on P123 board. .loop wrpin pincfg, pin cmp pin, #42 wz waitx #10 if_z drvl #38 drvl pin waitx #10 if_z outh #38 outh pin waitx count testp pin wz if_nz mov pb, #"0" if_z mov pb, #"1" call #putch dirl pin ' outl pin djnf pin, #.loop call #putnl cmp count, #7 wc 'C = borrow of (D - S) if_c ijnz count, #.count ret wcz diag11 byte 13,10," OUT fed back",13,10,"w 60 . . . .50 . . . .40 . . . .30 . . . .20 . . . .10 . . . . 0",13,10,0 diag12 byte 13,10," Unregistered",13,10,"w 60 . . . .50 . . . .40 . . . .30 . . . .20 . . . .10 . . . . 0",13,10,0 diag13 byte 13,10," Registered",13,10,"w 60 . . . .50 . . . .40 . . . .30 . . . .20 . . . .10 . . . . 0",13,10,0 {{ 3v3 VIO supply current UnClkd Clocked MHz | mA mA =====|============== 10 | 1.0 2.6 50 | 1.5 9.6 100 | 2.2 18.4 150 | 2.95 27.0 200 | 3.7 35.7 250 | 4.4 44.2 300 | 5.1 52.6 350 | 5.8 60.9 5v supply current (68.6 mOhm through meter) UnClkd Clocked MHz | mA mA =====|============== 10 | 57 58 100 | 170 185 200 | 290 320 300 | 406 456 350 | 464 520 }} '******************************************************************************* ' Subroutines '******************************************************************************* ORGH ALIGNL '=============================================== _diaginit ' Only called once at beginning 'FPGA frequencies ' hubset #$0f 'change to 5 MHz sysclock ' hubset #$1f 'change to 10 MHz sysclock ' hubset #$2f 'change to 15 MHz sysclock ' hubset #$3f 'change to 20 MHz sysclock ' hubset #$4f 'change to 25 MHz sysclock ' hubset #$5f 'change to 30 MHz sysclock ' hubset #$6f 'change to 35 MHz sysclock ' hubset #$7f 'change to 40 MHz sysclock ' hubset #$8f 'change to 45 MHz sysclock ' hubset #$9f 'change to 50 MHz sysclock ' hubset #$af 'change to 55 MHz sysclock ' hubset #$bf 'change to 60 MHz sysclock ' hubset #$cf 'change to 65 MHz sysclock ' hubset #$df 'change to 70 MHz sysclock ' hubset #$ef 'change to 75 MHz sysclock ' hubset #$ff 'change to 80 MHz sysclock 'Silicon frequencies hubset #0 'set 20MHz+ mode hubset ##_SETFREQ 'setup oscillator waitx ##20_000_000/100 '~10ms hubset ##_ENAFREQ 'enable oscillator 'Detect available smart pins 'Returns total number of available smart pins 'and a 64 bit mask indicating active smart pins. mov available, #0 mov smart_pin, #63 'test all 64 pins .searchloop wrpin #%11_0, smart_pin 'long repository mode dirh smart_pin mov pattern, ##$c0ffee00 add pattern, smart_pin 'unique pattern wxpin pattern, smart_pin 'write long to smart pin shl mask_lsb, #1 wc 'build valid smart pin mask rcl mask_msb, #1 rdpin response, smart_pin 'get long from smart pin repository cmp response, pattern wz 'valid response? if_e add available, #1 if_e bith mask_lsb, #0 dirl smart_pin wrpin #0, smart_pin 'disable smart pin djnf smart_pin, #.searchloop 'next smart pin '-------- Copy lut code into position -------- setq2 #(LUT_end - LUT_code - 1) 'copy length, in longwords rdlong 0, ##@LUT_code 'the "0" is lutRAM zero, or $200 in memory map '----- Configure diag comport to use smartpins instead of bit-bashing ----- wrpin #%00_11111_0, #rx_pin 'Asynchronous serial receive wxpin ##asynconfig, #rx_pin 'set baurdrate and framing dirh #rx_pin wrpin #%01_11110_0, #tx_pin 'Asynchronous serial transmit mode wxpin ##asynconfig, #tx_pin 'set X with baudrate and framing dirh #tx_pin 'release Z from zero wypin #0, #tx_pin 'trigger first tx ready state (not needed if dual checked) 'single check is buffer full only, dual checking adds in tx flag waitx sec 'delay for diag terminal to start mov bcdlen, #3 'emit smartpin report loc pa, #\@initmsg3 call #puts mov pa, available call #itod call #putsp mov pa, mask_msb call #itob mov pa, mask_lsb call #itob ' jmp #putnl 'emit sysclock frequency loc pa, #\@initmsg1 call #puts mov pa, #clock_freq/1000000 call #itod loc pa, #\@initmsg2 call #puts jmp #_main initmsg3 byte 10,13,"Total smartpins =",0 initmsg1 byte 10,13,"System clock frequency set to ",0 initmsg2 byte " MHz",10,13,0 ORG 'Note these overlay first seven longwords in cogRAM 'Special reservation is made for location #1 "sec" available res 2 mask_lsb res 1 mask_msb res 1 pattern res 1 response res 1 smart_pin res 1 ORG $200 'longword addressing '******************************************************************************* ' LUT Code (Has to be copied from hubram to lutram) '******************************************************************************* LUT_code '=============================================== 'Integer multiply 32-bit x 16-bit. pa = pa x pb. 10 clocks ' input: pa, pb ' result: pa 'scratch: temp1 ' mul32x16 getword temp1, pa, #1 mul temp1, pb 'pah * pbl mul pa, pb 'pal * pbl shl temp1, #16 _ret_ add pa, temp1 '=============================================== 'Integer multiply 32-bit x 32-bit. pa = pa x pb. 16 clocks ' input: pa, pb ' result: pa 'scratch: temp1, temp2 ' mul32x32 getword temp1, pa, #1 getword temp2, pb, #1 mul temp1, pb 'pah * pbl mul temp2, pa 'pal * pbh mul pa, pb 'pal * pbl add temp1, temp2 shl temp1, #16 _ret_ add pa, temp1 '=============================================== 'Integer multiply 64-bit x 32-bit. r64 = a64 x pb. 52 clocks excluding CALL/RET ' input: a64, pb (all remain intact) ' result: r64 'scratch: temp1, temp2, a1, a3, b1 ' mul64x32 getword a1, a64, #1 getword a3, a64h, #1 getword b1, pb, #1 mov temp1, a64h mul temp1, pb 'a2 * b0 mov r64h, a1 mul r64h, b1 '6: high, a1 * b1 add r64h, temp1 '3: high mul a3, pb 'a3 * b0 mov temp2, a64h mul temp2, b1 'a2 * b1 add temp2, a3 '4: high shl temp2, #16 add r64h, temp2 '7: high mov r64, a64 mul r64, pb '1: low, a0 * b0 mul a1, pb 'a1 * b0 mul b1, a64 'a0 * b1 getword temp1, a1, #1 getword temp2, b1, #1 shl a1, #16 shl b1, #16 add r64, a1 wc '2: low addx r64h, temp1 '2: high add r64, b1 wc '5: low addx r64h, temp2 '5: high ret wcz '=============================================== ' input: (none) ' result: pb 'scratch: (none) ' getch testp #rx_pin wz 'byte received? (IN high == yes) if_z rdpin pb, #rx_pin 'get data if_z shr pb, #32-8 'shift the data to bottom of register if_z ret wcz 'restore C/Z flags of calling routine jmp #getch 'wait while Smartpin is idle '=============================================== ' input: pb ' result: (none) 'scratch: (none) ' putch rqpin inb, #tx_pin wc 'transmiting? (C high == yes) *Needed to initiate tx testp #tx_pin wz 'buffer free? (IN high == yes) if_z_or_nc wypin pb, #tx_pin 'write new byte to Y buffer if_z_or_nc ret wcz 'restore C/Z flags of calling routine jmp #putch 'wait while Smartpin is both full (nz) and transmitting (c) '=============================================== 'Emit CR/LF ' input: (none) ' result: (none) 'scratch: pb ' putnl mov pb, #13 call #putch mov pb, #10 jmp #putch '=============================================== 'Emit three spaces ' input: (none) ' result: (none) 'scratch: pb ' putsp mov pb, #" " call #putch call #putch jmp #putch '=============================================== 'Emit status of C/Z flags ' input: (C/Z flags) ' result: (none) 'scratch: pb ' emitflags mov pb, #"C" call #putch mov pb, #"=" call #putch if_c mov pb, #"1" if_nc mov pb, #"0" call #putch call #putsp mov pb, #"Z" call #putch mov pb, #"=" call #putch if_z mov pb, #"1" if_nz mov pb, #"0" call #putch jmp #putnl '=============================================== 'Emit string ' input: pa - hubRAM address of string ' result: (none) 'scratch: pa, pb ' puts rdbyte pb, pa wz if_z ret wcz 'null termination, C/Z preserved call #putch 'emit character ijnz pa, #puts 'increment pointer (assumes non-zero address) '=============================================== 'Integer (32-bit) to ascii binary and emit ' input: pa ' result: (none) 'scratch: pa, pb, bcdi ' itobl rev pa 'least significant first itob mov bcdi, #32 .emit rol pa, #1 wc if_nc mov pb, #"0" if_c mov pb, #"1" call #putch djnz bcdi, #.emit ret wcz 'restore C/Z flags of calling routine '=============================================== 'Integer (32-bit) to ascii hexidecimal and emit ' input: pa ' result: (none) 'scratch: pa, pb, bcdi ' itohl rev pa 'least significant first itoh mov bcdi, #7 'most significant nibble first (zero extended) .emit altgn bcdi, #pa '(instruction prefix) getnib pb 'retrieve next hex digit from pa register: pb = pa[bcdi] cmp pb, #10 wcz 'test if below 10, C = borrow of (D - S) if_c add pb, #"0" 'ASCII encode 0-9 if_nc add pb, #"a"-10 'ASCII encode a-f call #putch djnf bcdi, #.emit ret wcz 'restore C/Z flags of calling routine '=============================================== 'Integer (32-bit) to ascii decimal and emit ' Note: Uses the CORDIC. This means that any already running operations will be corrupted ' Also requires bcdlen set for the number of digits to be emitted ' input: pa, bcdlen ' result: (none) 'scratch: pa, pb, bcdi, bcdstr ' itod 'bundle 32-bit integer to BCD string qdiv pa, #10 'had to cheat. It's hard without divide and modulo mov bcdstr, #0 'clear bcdstr to all zeros mov bcdstr+1, #0 mov bcdi, #0 'reset digit index fle bcdlen, #16 'hard limit of 16 digits for string length fge bcdlen, #1 ' .makebcd getqx pa wz 'collect result for recursion getqy pb 'collect decimal digit if_nz qdiv pa, #10 'recurse for next digit altsn bcdi, #bcdstr '(instruction prefix) setnib 0-0, pb, #0-0 '(p2asm neeeds extended form) File the decimal digit as BCD: bcdstr[bcdi] = pb add bcdi, #1 if_nz jmp #.makebcd 'Emit BCD as a string to comport fge bcdi, bcdlen 'set minimum string length sub bcdi, #1 wz 'to suit zero based indexing if_z jmp #.emit .leadin altgn bcdi, #bcdstr '(instruction prefix) getnib pb 'retrieve next digit from BCD: pb = bcdstr[bcdi] cmp pb, #0 wz if_z mov pb, #" " 'replace with leading spaces if_z call #putch 'Relies on #putch preserving C/Z flags if_z djnz bcdi, #.leadin .emit altgn bcdi, #bcdstr '(instruction prefix) getnib pb 'retrieve next digit from BCD: pb = bcdstr[bcdi] add pb, #"0" 'encode ASCII call #putch djnf bcdi, #.emit ret wcz 'restore C/Z flags of calling routine LUT_end FIT $400