CON _XTALFREQ = 20_000_000 'PLL stage 0: crystal frequency _XDIV = 2 'PLL stage 1: crystal divider _XMUL = 2 '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 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) '******************************************************************************* 'i hubset #$0f 'change to 5 MHz sysclock 'i hubset #$1f 'change to 10 MHz sysclock 'i hubset #$2f 'change to 15 MHz sysclock 'i hubset #$3f 'change to 20 MHz sysclock 'i hubset #$4f 'change to 25 MHz sysclock 'i hubset #$5f 'change to 30 MHz sysclock 'i hubset #$6f 'change to 35 MHz sysclock 'i hubset #$7f 'change to 40 MHz sysclock 'i hubset #$8f 'change to 45 MHz sysclock 'i hubset #$9f 'change to 50 MHz sysclock 'i hubset #$af 'change to 55 MHz sysclock 'i hubset #$bf 'change to 60 MHz sysclock 'i hubset #$cf 'change to 65 MHz sysclock 'i hubset #$df 'change to 70 MHz sysclock 'i hubset #$ef 'change to 75 MHz sysclock 'i hubset #$ff 'change to 80 MHz sysclock '+-------[ Set Xtal ]----------------------------------------------------------+ i hubset #0 ' set 20MHz+ mode j hubset ##_SETFREQ ' setup oscillator k waitx ##20_000_000/100 ' ~10ms char hubset ##_ENAFREQ ' enable oscillator '+-----------------------------------------------------------------------------+ bcdlen call #diaginit bcdi waitx sec 'delay for diag terminal to start bcdstr temp1 shr sec, #2 'adjust to 1/4 second temp2 mov i, #1 temp rep @erasel, #erasel 'zero out all working registers bits alti i, #%111_000 tickstart mov 0-0, #0 erasel coginit #%10001, ##@start_sinc3 'start paired cogs for filtered Sinc3 monitor output jmp #_main ' 'data ' 'asynconfig long (clock_freq * 64 / baud_rate * 1024) | 7 'bitrate format is 16.6<<10, 8N1 framing 'clock_freq max of 31 MHz 'asynconfig long (clock_freq * 8 / (baud_rate / 8) * 1024) | 7 'bitrate format is 16.6<<10, 8N1 framing 'clock_freq max of 255 MHz asynconfig long (clock_freq * 4 / (baud_rate / 16) * 1024) | 7 'bitrate format is 16.6<<10, 8N1 framing 'clock_freq max of 511 MHz sec long clock_freq FIT '******************************************************************************* ' HUB Code '******************************************************************************* ORGH $400 ALIGNL _main mov bcdlen, #12 loc pa, #\@diag1 call #puts mov pa, asynconfig call #itoh call #putnl mov pa, ##clock_freq call #itod getct tickstart '------ LED diag toggle for sysclock measuring ------- rep @.rend,#3 drvnot #33 drvnot #56 waitx ##clock_freq .rend getct pa sub pa, tickstart call #itod call #putnl mov bcdlen, #5 diagloop testp #mailb1 wz testp #mailb2 orz if_z waitx #500 if_z rdpin pa, #mailb1 if_z call #itod if_z rdpin pa, #mailb2 if_z call #itod if_z call #putnl jmp #diagloop str1 byte "loc pa, #label ",0 str2 byte "loc pa, #@label ",0 str3 byte "loc pa, #\label ",0 str4 byte "loc pa, #\@label",0 str5 byte "mov pa, #label ",0 str6 byte "mov pa, ##label ",0 str7 byte "mov pa, ##@label",0 titlestart byte 13,10,13,10," LOC/MOV syntax ORG $00F ORGH $00110 ORGH $00600",13,10,0 titleend byte " op-code PA-data op-code PA-data op-code PA-data",13,10,"==============================================================================",13,10,0 titlehub byte " from hubRAM ",0 titlecog byte " from cogRAM ",0 diag1 byte 13,10,"Diag comport pins: ",0 diag2 byte " Config = ",0 CON dacpin = 9 'DAC smartpin adcpin = 0 'ADC smartpin for bitstream data input (MDAT) clkpin = 2 'ADC smartpin for bitstream clock input (MCLK) mailb1 = 5 'debug mailboxes mailb2 = mailb1+1 mailb3 = mailb1+2 DAT '================================== ' paired mailbox '================================== ORG $3fe monitor res 1 'duration res 1 '================================== ' Sinc3 filter (cogexec, paired) '================================== ORG start_sinc3 cid cogid cid testb cid, #0 wz if_z jmp #start_monitor 'identical code on paired cogs delay wrpin #%00011_0, #mailb3 'smartpin as a mailbox key dirh #mailb3 wrpin ##%0000_100000000_00_01111_0, #adcpin 'adc/counter mode, clocked wypin #0, #adcpin 'inc on high wxpin #0, #adcpin 'totaliser dirh #adcpin 'enable smart pin 'Sinc3 loop (8 sysclocks) rep @.lend, #0 'loop forever rdpin acc1, #adcpin add acc2, acc1 add acc3, acc2 ' wrlut acc3, #(monitor & $1ff) 'for the decimator (lut sharing is active) ' add acc4, acc3 ' wrlut acc4, #(monitor & $1ff) 'for the decimator (lut sharing is active) wxpin acc3, #mailb3 'for the decimator .lend cogstop cid acc1 diff1 long 0 acc2 diff2 long 0 acc3 diff3 long 0 acc4 diff4 long 0 period long 40 'max 1024 clocks, needs 30-bit registers dbg long 0 'dacmode long %101_00_00000000_01_00000_0 'DAC mode for DAC1/Blue, using SETDACS dacmode long %101_00_00000000_01_00010_0 'DAC mode for DAC1/Blue, using 16-bit dither smartpin mode '============================ ' Monitor (cogexec, paired) '============================ start_monitor ' lutson samp1 wrpin #%01_00011_0, #mailb1 'smartpin as a mailbox, for diag. Includes out drive for scope trigger samp2 dirh #mailb1 samp3 wrpin #%00011_0, #mailb2 'smartpin as a mailbox, for diag samp4 dirh #mailb2 samp setbyte dacmode, cid, #1 filt wrpin dacmode, #dacpin wxpin #1, #dacpin 'continuous dither wypin #0, #dacpin 'initial DAC level offset dirh #dacpin 'enable DAC 'scale setse1 #%110_000000|rx_pin 'high IN from smartpin scale setse1 #%001_000000|rx_pin 'rising IN from smartpin 'keyboard controls '=================== .keyboard rdpin key, #rx_pin 'fetch received keypress, clears IN event source shr key, #32-8 'lsbit align cmp key, #"+" wz if_z add offset, #511 '16-bit cmp key, #"-" wz if_z sub offset, #511 '16-bit pollse1 'clear event, needs four extra clocks for IN to drop akpin #rx_pin 'scaling recalculation encod scale, period add scale, #1 '8-clock Sinc3 shr scale, #2 mul scale, #8 '10-clock Sinc4 ' shr scale, #2 ' mul scale, #10 cmp key, #"*" wz if_z add period, scale cmp key, #"/" wz if_z sub period, scale fles period, ##2048 'max of 1024 (250) clocks, multiple of 8 (10) fges period, #40 'fastest monitor loop time, multiple of 8 (10) mov delay, period sub delay, #38 outnot #mailb1 'pin #0 toggle for scope trigger waitx #56 'lutRAM sharing flaw!! Change the #6 to hide it outnot #mailb1 'pin #0 toggle for scope trigger wxpin period, #mailb2 'second mailbox for reporting pollse1 'reset box filter mov filt, #0 mov samp1, #0 mov samp2, #0 mov samp3, #0 mov samp4, #0 'monitor loop ' '============== ' rep @.monend, #0 'loop forever (REP reduces monitor loop by two instructions) .monl waitx delay '2 WAITX reduces monitor loop by one instruction jse1 #.keyboard '4 branch on event reduces monitor loop by one instruction 'decimator ' rdlut samp, #(monitor & $1ff) '7 rdpin samp, #mailb3 '6 sub samp, diff1 '8 9 add diff1, samp '10 11 sub samp, diff2 '12 13 add diff2, samp '14 15 sub samp, diff3 '16 17 add diff3, samp '18 19 ' sub samp, diff4 '20 ' add diff4, samp '22 'chop off lower bits ' shr samp, #4 '20 21 'offset centring add samp, offset '22 23 ' wypin samp, #dacpin '24 smartpin 16-bit dither into DAC1 'FIR box filter sub filt, samp3 '24 25 mov samp4, samp3 '26 27 mov samp3, samp2 '28 29 mov samp2, samp1 '30 31 mov samp1, samp '32 33 add filt, samp '34 35 wypin filt, #dacpin '36 37 smartpin 16-bit dither into DAC1 ' setdacs filt '36 upper 8 of 16 bits into DAC1 .monend jmp #.monl '38 41 'This code is workaround for intermittent problem with event branching out from REP loops ' occasionly it just drops the branch and falls out the bottom of the REP add dbg, #1 wxpin dbg, #mailb1 'mailbox for reporting occurances jmp #\.keyboard jmp #\.keyboard 'needs double JMP to recover cogstop cid FIT '******************************************************************************* ' Subroutines '******************************************************************************* ORGH ALIGNL '=============================================== diaginit ' Only called once at beginning '-------- 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 _ret_ 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 ORG $200 'longword addressing '******************************************************************************* ' LUT Code (Has to be copied from hubram to lutram) '******************************************************************************* LUT_code '=============================================== getch testp #rx_pin wz if_nz jmp #getch 'wait while Smartpin is idle rdpin char, #rx_pin shr char, #32-8 'shift the data to bottom of register ret wcz 'restore C/Z flags of calling routine '=============================================== putch ' rqpin temp1, #tx_pin wc 'transmiting? (read Z to see if actively shifting out) testp #tx_pin wz 'buffer free? (IN state shows Y buffer full status) 'if_nz_and_c jmp #putch 'wait while Smartpin is both full (nz) and transmitting (c) if_nz jmp #putch 'wait while Smartpin is full (nz) wypin char, #tx_pin 'write new byte to Y buffer ret wcz 'restore C/Z flags of calling routine '=============================================== 'CR/LF emit putnl mov char, #13 call #putch mov char, #10 jmp #putch '=============================================== 'Space emit putsp mov char, #" " call #putch mov char, #" " call #putch mov char, #" " jmp #putch '=============================================== 'String emit puts rdbyte char, 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 (long) to ascii binary and emit itobl rev pa 'least significant first itob mov bcdi, #32 .emit rol pa, #1 wc if_nc mov char, #"0" if_c mov char, #"1" call #putch djnz bcdi, #.emit ret wcz 'restore C/Z flags of calling routine '=============================================== 'Integer (long) to ascii hexidecimal and emit itohl rev pa 'least significant first itoh mov bcdi, #7 'most significant nibble first (zero extended) .emit altgn bcdi, #pa '(instruction prefix) getnib char 'retrieve next hex digit from pa register: char = pa[bcdi] cmp char, #10 wcz 'test if below 10, C = borrow of (D - S) if_c add char, #"0" 'ASCII encode 0-9 if_nc add char, #"a"-10 'ASCII encode a-f call #putch djnf bcdi, #.emit ret wcz 'restore C/Z flags of calling routine '=============================================== 'Integer (long) 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 itod 'convert 32-bit integer to BCD 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, #15 'hard limit of 15 digits for string length .makebcd getqx pa wz 'collect result for recursion getqy char 'collect decimal digit if_nz qdiv pa, #10 'recurse for next digit altsn bcdi, #bcdstr '(instruction prefix) setnib 0-0, char, #0-0 'file the decimal digit as BCD: bcdstr[bcdi] = chr if_nz ijnz bcdi, #.makebcd 'Emit BCD as a string to comport fge bcdi, bcdlen 'set minimum string length .leadin altgn bcdi, #bcdstr '(instruction prefix) getnib char 'retrieve next digit from BCD: char = bcdstr[bcdi] cmp char, #0 wz if_z mov char, #" " '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 char 'retrieve next digit from BCD: char = bcdstr[bcdi] add char, #"0" 'encode ASCII call #putch djnf bcdi, #.emit ret wcz 'restore C/Z flags of calling routine LUT_end FIT $400