|
| 1 | +' Program reads 1..8 consecutive ADC pins and displays millivolts for each. |
| 2 | +' A terminate-stay-resident PASM program performs conversions in background. |
| 3 | +' Samples are always available via REG[samples][{0..7}]. |
| 4 | + |
| 5 | +CON |
| 6 | + _clkfreq = 297_000_000 'set clock frequency |
| 7 | + _pins = 16 addpins 7 'do conversions on these pins |
| 8 | + |
| 9 | +OBJ |
| 10 | + vga : "VGA_640x480_text_80x40" '_clkfreq >= 50MHz |
| 11 | +' vga : "VGA_1280x1024_text_160x85" '_clkfreq >= 216MHz |
| 12 | +' vga : "HDTV_1920x1080_text_240x90" '_clkfreq >= 297MHz |
| 13 | +' vga : "HDTV_1920x1080_text_135x160" '_clkfreq >= 297MHz |
| 14 | + |
| 15 | +PUB go() | i |
| 16 | + |
| 17 | + vga.start(8) 'start vga |
| 18 | + |
| 19 | + reg[pins] := _pins 'set 'pins' variable |
| 20 | + regexec(@adc_pasm) 'launch PASM program (uses 'pins') |
| 21 | + |
| 22 | + send := @vga.print 'set send pointer |
| 23 | + |
| 24 | + repeat 'print samples set every 100ms |
| 25 | + repeat i from 0 to _pins >> 6 |
| 26 | + send(dec4(reg[samples][i]), "mV ") |
| 27 | + send(13) |
| 28 | + waitms(100) |
| 29 | + |
| 30 | +PRI dec4(value) | digflag, negflag, place, digit |
| 31 | + |
| 32 | + digflag~ |
| 33 | + negflag := value < 0 |
| 34 | + abs= value |
| 35 | + place := 1_000 |
| 36 | + repeat |
| 37 | + if digflag || (digit := value / place // 10) or place == 1 |
| 38 | + if not digflag~~ |
| 39 | + send(negflag ? "-" : " ") |
| 40 | + send("0" + digit) |
| 41 | + else |
| 42 | + send(" ") |
| 43 | + if place == 1_000 |
| 44 | + send(digflag ? "," : " ") |
| 45 | + while place /= 10 |
| 46 | + |
| 47 | +DAT |
| 48 | + |
| 49 | +'******************************************************** |
| 50 | +'* PASM Program which launches via REGEXEC * |
| 51 | +'* Sets up an interrupt and then runs in the background * |
| 52 | +'* Performs calibrated ADC measurements of up to 8 pins * |
| 53 | +'* Reports samples in millivolts * |
| 54 | +'******************************************************** |
| 55 | +' |
| 56 | +' |
| 57 | +' REGEXEC header words |
| 58 | +' |
| 59 | +adc_pasm word adc_start 'initial register to load |
| 60 | + word adc_end-adc_start-1 'additional registers to load |
| 61 | + |
| 62 | + org $B0 'put PASM code up high |
| 63 | +' |
| 64 | +' |
| 65 | +' ADC program setup |
| 66 | +' |
| 67 | +adc_start fltl pins 'set pins to ADC mode |
| 68 | + wrpin adc_modes,pins |
| 69 | + wxpin #9,pins '#9 is 512-clock, 10-bit conversion (8 per sample) |
| 70 | + drvl pins 'start pins on same clock |
| 71 | + |
| 72 | + mov pin_base,pins 'get pin base |
| 73 | + and pin_base,#$3F |
| 74 | + |
| 75 | + mov pin_count,pins 'get pin count |
| 76 | + shr pin_count,#6 |
| 77 | + add pin_count,#1 |
| 78 | + |
| 79 | + mov level_base,#adc_levels 'prepare level_base altd pointer |
| 80 | + sub level_base,pin_base |
| 81 | + bith level_base,#9 |
| 82 | + |
| 83 | + mov ijmp1,#adc_isr 'set interrupt jump |
| 84 | + |
| 85 | + mov x,pin_base 'set base pin IN-rise event |
| 86 | + or x,#%001<<6 |
| 87 | + setse1 x |
| 88 | + |
| 89 | + _ret_ setint1 #event_se1 'enable interrupt on event, return to Spin2 |
| 90 | +' |
| 91 | +' |
| 92 | +' ADC interrupt service routine - runs in background of Spin2 interpreter |
| 93 | +' |
| 94 | +adc_isr akpin pins 'ADC samples done, acknowledge pins |
| 95 | + |
| 96 | + alts cycle,#vio_levels 'lookup vio and gio levels for sample computation |
| 97 | + mov x,0 |
| 98 | + alts cycle,#gio_levels |
| 99 | + mov y,0 |
| 100 | + |
| 101 | + sub x,y '(3300 << 12) / (vio_level - gio_level) |
| 102 | + qdiv ##3300<<12,x 'cordic runs during REP |
| 103 | + |
| 104 | + rep #3,pin_count 'read ADC samples and sum into adc_levels |
| 105 | + rdpin x,pin_base |
| 106 | + altd pin_base,level_base |
| 107 | + add 0,x |
| 108 | + |
| 109 | + sub pin_base,pin_count 'restore pin_base |
| 110 | + |
| 111 | + getqx x 'get QDIV quotient |
| 112 | + |
| 113 | + alts cycle,#pin_levels '(quotient * (pin_level - gio_level)) >> 12 |
| 114 | + subr y,0 |
| 115 | + muls y,x |
| 116 | + sar y,#12 |
| 117 | + |
| 118 | + altd cycle,#samples 'write finished sample |
| 119 | + mov 0,y |
| 120 | + |
| 121 | + incmod cycle,#7 wc 'repeat for 8 cycles |
| 122 | + if_nc reti1 'return to Spin2 |
| 123 | + |
| 124 | + |
| 125 | + altd state,#adc_modes 'end of 8th cycle, switch to next gio/vio/pin |
| 126 | + wrpin 0,pins |
| 127 | + |
| 128 | + resi1 'return to Spin2, resume on next interrupt |
| 129 | + |
| 130 | + |
| 131 | + akpin pins '9th cycle, acknowledge pins |
| 132 | + |
| 133 | + alts state,#moves 'move adc_levels to gio/vio/pin_levels |
| 134 | + mov x,0 |
| 135 | + rep #2,pin_count |
| 136 | + alti x,#%111_111 |
| 137 | + mov 0,0 |
| 138 | + |
| 139 | + resi1 'return to Spin2, resume on next interrupt |
| 140 | + |
| 141 | + |
| 142 | + akpin pins '10th cycle, acknowledge pins |
| 143 | + |
| 144 | + setd x,#adc_levels 'clear adc_levels |
| 145 | + rep #2,pin_count |
| 146 | + alti x,#%111_000 |
| 147 | + mov 0,#0 |
| 148 | + |
| 149 | + incmod state,#3 'increment state |
| 150 | + |
| 151 | + mov ijmp1,#adc_isr 'return to Spin2, start over on next interrupt |
| 152 | + reti1 |
| 153 | +' |
| 154 | +' |
| 155 | +' Defined data |
| 156 | +' |
| 157 | +cycle long 0 'cycles {0..7, 0, 0} for each state |
| 158 | +state long 0 'states {0..3} |
| 159 | + |
| 160 | +adc_modes long p_adc_gio | p_adc 'adc modes, by state |
| 161 | + long p_adc_1x | p_adc |
| 162 | + long p_adc_vio | p_adc |
| 163 | + long p_adc_1x | p_adc |
| 164 | + |
| 165 | +moves long pin_levels<<9 | adc_levels 'moves, by state |
| 166 | + long gio_levels<<9 | adc_levels |
| 167 | + long pin_levels<<9 | adc_levels |
| 168 | + long vio_levels<<9 | adc_levels |
| 169 | + |
| 170 | +adc_end 'end of PASM code to load into registers |
| 171 | +' |
| 172 | +' |
| 173 | +' Undefined data |
| 174 | +' |
| 175 | +pins res 1 'initially set by Spin2 code to select the pins |
| 176 | + |
| 177 | +x res 1 |
| 178 | +y res 1 |
| 179 | +pin_base res 1 |
| 180 | +pin_count res 1 |
| 181 | +level_base res 1 |
| 182 | + |
| 183 | +adc_levels res 8 'conversions are accumulated into this buffer |
| 184 | +gio_levels res 8 '..and then copied to one of these three buffers |
| 185 | +vio_levels res 8 |
| 186 | +pin_levels res 8 |
| 187 | + |
| 188 | +samples res 8 'final samples, available via REG[samples][{0..7}] |
| 189 | +' |
| 190 | +' |
| 191 | +' cycle operations |
| 192 | +' ------------------------------------------------------------------------------------ |
| 193 | +' 0 (1st) add conversions to levels, compute sample[0] |
| 194 | +' 1 add conversions to levels, compute sample[1] |
| 195 | +' 2 add conversions to levels, compute sample[2] |
| 196 | +' 3 add conversions to levels, compute sample[3] |
| 197 | +' 4 add conversions to levels, compute sample[4] |
| 198 | +' 5 add conversions to levels, compute sample[5] |
| 199 | +' 6 add conversions to levels, compute sample[6] |
| 200 | +' 7 (8th) add conversions to levels, compute sample[7], switch to gio/vio/pin |
| 201 | +' 0 (9th) move levels to gio/vio/pin_levels |
| 202 | +' 0 (10th) clear levels, advance state |
| 203 | +' |
| 204 | +' state operations |
| 205 | +' ------------------------------------------------------------------------------------ |
| 206 | +' 0 sample gio for calibration |
| 207 | +' 1 sample pin for signal |
| 208 | +' 2 sample vio for calibration |
| 209 | +' 3 sample pin for signal |
| 210 | +' |
0 commit comments