Shop OBEX P1 Docs P2 Docs Learn Events
QuadView 4-in1 artifact color driver - Page 2 — Parallax Forums

QuadView 4-in1 artifact color driver

2»

Comments

  • roglohrogloh Posts: 5,171
    edited 2021-10-03 13:25

    Oddly enough, I haven't gotten satisfactory composite video from the actual video hardware yet, neither from @rogloh's code nor Chips. Satisfactory as-in "at least as good as P1 composite".

    It's really hard (at least for me) to get this composite stuff right. I'd started out with Chip's original NTSC code and added some changes for PAL. Then later Chip updated some composite code demos with more accurate calculations which did improve this a little more, but none of that has made it into my driver yet....I need to revisit when I have time. I was hoping to use standard timing and not cut corners or come up with weird line counts that "look better" for some devices and probably worse for others. Hoping for help there. But if it goes beyond tweaking parameter values, any other code changes also need to fit in my driver's footprint otherwise it's unlikely to make it in.

  • Bonus because I had it on today: QuadView Boing ball, as seen on the big Phillips. Hard to get a good shot with it bouncing around so much :3

  • Was that with S-video or composite output? If it's the latter in general its looks fairly clean, apart from tearing/ghosting due to movement during photo. Maybe just a little crawl in portions of the vertical white lines. Still seems reasonably nice in this shot.

  • @rogloh said:
    Was that with S-video or composite output? If it's the latter in general its looks fairly clean, apart from tearing/ghosting due to movement during photo. Maybe just a little crawl in portions of the vertical white lines. Still seems reasonably nice in this shot.

    Artifact color only works for composite (well, you can use two channels as luma+chroma, but that really defeats the point)

  • When the level of the chroma channel can change, using the S-video input can yield cleaner artifacts. One of these days I need to develop a little active circuit, but a small cap on the chroma line, and resistor can work great for this type of color when using S-video. Many devices, especially PVM types, use a different set of filters on their S-video signal path. Those can get in the way of a good display.

    As far as I can tell, there is no phase lock between the chroma signal and the pixel clock.

    P1 had the same problem, and I found it when creating artifact colors by abusing the P1 standard colors. On start up, it was one of 16 possibilities. However, it was also stable as the whole thing ran off the PLLA.

    Eric Ball came along and basically did the whole signal with the pixels only, and it worked great! Software colorburst. The Nyan Cat demo floating around is an example of that in use.

    That driver did not use a phase shifted colorburst.

    When I saw the shimmer on P2, it came down to the NCO and a rolling error between pixel clock and the output of the color system.

    Thought giving that up, then doing color with a fixed, software colorburst would do the trick same as it did on P1. I got excited to see you did the phase change colorburst, because that would essentially take artifact color to 320 pixels in the active area from the usual color cycle locked 160.

    I hope to run this on my displays to see what I see.

    The ball looks pretty good. The image before looks almost like the chroma is way over spec, but that could just be the colors generated too.

    Can't really comment more without reviewing the code in front of a display.

    I will say, the P2 HOT chip, which did use a PLL, output awesome composite, but also did exhibit the phase difference all Propeller chips have had, but it was stable like P1 was.

    I had a few ideas:

    One being to drive the P2 with a colorburst crystal.

    Another being to find a NCO combination and crystal that nails 13.500Mhz which can work for this sort of thing and or a stable signal with the color circuit, similar to the HOT chip.

    Reset the NCO every field and let the display deal with that during the blank.

  • cgraceycgracey Posts: 14,133

    Calculating very accurate NCO values can push the beat frequencies below 0.1 Hz.

  • That, and a per field reset may work well Chip.

    Sorry I have been scarce everyone! I follow all the projects and see a lot of awesome progress! Have had quite a bit land on my plate, some bad, a whole lot good, but it takes most of what I got right now.

  • If you run at exactly 64x colorburst (~229Mhz), the NCO value becomes a power of 2 and thus no phase slip. But that's a rather low speed, so not an option in many cases.

    One particular problem I've noticed is that Spin2 has no way to compute the correct NCO value. Let's assume the sysclock is 90x colorburst, so we want 1/90 CFREQ:

    • The correctly rounded value is $2D82D83
    • round(4_294_967_296.0/90.0) will give a value of $2D82D84
    • 1 frac 90 will give $2D82D82
  • Would there be value in swapping your board crystal for 3.579545MHz or 14.31818MHz?

  • @Circuitsoft said:
    Would there be value in swapping your board crystal for 3.579545MHz or 14.31818MHz?

    No, the actual frequency doesn't matter, the relationship between frequencies does. The whole clock multiply/divide thing gets close enough to where the decoder can lock on and that's all that matters.

  • I've been thinking recently about a possible method to get the P2 video DAC voltage levels increased to ~1.3Vpp in order to meet the correct voltages with full sync tip levels and with 100% colour bars using a composite signal. The approach would be to wire two P2 pins together (which are both generating the exact same composite signal using DAC channels 0 & 1) with a series resistor at each pin feeding a common video output which then gets shunted to ground via another resistance to create the same 75 ohm source impedance as we have now.

    With the 3.3V DAC mode having its own impedance of 123.75 ohms I think using 56 ohms for each series resistor plus a 470ohm and 12k resistor in parallel, making 452 ohms as the shunt resistance should give an increased DAC range. It would then let you drive up to 1.37Vpp into a 75 ohm load instead of 1Vpp. Something like this circuit below.


    It could be interesting to try it out. With full sync tips on a composite signal it would reduce the dynamic range for the luma and chroma a little from the existing no resistor solution but it would at least cover the standard voltage range making it easier to tune the levels correctly with a scope and colour bars. Like before, the sync tips are not going drive out negative voltages but that's okay as video input devices should also clamp their blanking/black levels.

  • Using a THS7314 would be relatively cheap, and it includes a lowpass filter for cleaning up DAC outputs. Might be easier than using a second pin and trying to properly synchronize the outputs.

  • roglohrogloh Posts: 5,171
    edited 2021-10-06 05:42

    Yeah that device looks interesting too @Circuitsoft

    In the datasheet for this device I read this which might also explain why some of the NTSC stuff from P2 looks so bright/saturated if the sync pulse is not the full voltage (though it may also be device dependent):

    "Some video AGC circuits derive gain from the horizontal sync amplitude. If clipping occurs on the sync amplitude, then the AGC circuit can increase the gain too much–resulting in too much luma and/or chroma amplitude gain correction. This may result in a picture with an overly bright display with too much color saturation. Other AGC circuits use the chroma burst amplitude for amplitude control, and a reduction in the sync signals does not alter the proper gain setting. But, it is good engineering design practice to ensure saturation/clipping does not take place."

    Update: I would expect that the two P2 composite outputs should be well synchronized in the P2 DACs when both get sourced from the same X0 channel out of the TV modulator block, but that needs to be determined.

  • This is getting way off topic, should probably be split again....

    To be on-topic, QuadView actually does generate reasonably standard levels by way of being able to clip levels instead of overflowing. It really only affects saturated yellow.

    Relatedly, wouldn't just one 3.3v DAC get close enough? Impedance would be a bit off, but I don't think that's a huge issue?

    In terms of AGC, it seems that most devices do luma and chroma AGC separately (which is why reducing modulator levels just makes the artifacts worse) based on sync/blanking difference and color burst amplitude respecitively. Relatedly, I'm pretty sure nothing actually drives negative voltages for sync, there's no need.

  • ColeyColey Posts: 1,108

    This is fantastic Wuerfel_21, I'll see if I can get a picture tomorrow of it running on the 8 arcade cabinets ;-)

  • @Coley said:
    This is fantastic Wuerfel_21, I'll see if I can get a picture tomorrow of it running on the 8 arcade cabinets ;-)

    If you shoot me the code for reading the inputs, I can try making 8-in-1 Spin Hexagon happen, too ;3

  • @Wuerfel_21 said:

    @Coley said:
    This is fantastic Wuerfel_21, I'll see if I can get a picture tomorrow of it running on the 8 arcade cabinets ;-)

    If you shoot me the code for reading the inputs, I can try making 8-in-1 Spin Hexagon happen, too ;3

    I may have gotten started on that already. Mostly missing audio and highscore saving.

  • ColeyColey Posts: 1,108

    I've asked Baggers to post the code you need....
    Cabinets are finished now and Baggers will be showing them at PlayExpo retro computer show next weekend.

  • BaggersBaggers Posts: 3,019
    edited 2021-10-17 15:45

    Hi @Wuerfel_21,

    Here's the code split out from the 8in1

    Cheers,
    Jim.

    `'-------------------------------------------------------------------------------------------------

    rp = 2_200.0 'pull-up resistor to VIO (local 3.3V)
    r5 = 1_200.0 '1st button parallel resistor, should be approximately rp
    r4 = 600.0 '2nd button parallel resistor, should be approximately r1 * 2
    r3 = 300.0 '3rd button parallel resistor, should be approximately r2 * 2
    r2 = 150.0 '4th button parallel resistor, should be approximately r3 * 2
    r1 = 75.0 '5th button parallel resistor, should be approximately r4 * 2, connects to GND

    scale = 3300.0

    'calculate r1..r5 series resistance sums per button combination
    r00000 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
    r00001 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
    r00010 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
    r00011 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
    r00100 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
    r00101 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
    r00110 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
    r00111 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
    r01000 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
    r01001 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
    r01010 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
    r01011 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
    r01100 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
    r01101 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
    r01110 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
    r01111 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
    r10000 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
    r10001 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
    r10010 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
    r10011 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
    r10100 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
    r10101 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
    r10110 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
    r10111 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
    r11000 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
    r11001 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
    r11010 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
    r11011 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
    r11100 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
    r11101 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
    r11110 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
    r11111 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
    `

    'calculate ADC voltage readings per button combination v00000 = round(scale * r00000 / (rp + r00000)) v00001 = round(scale * r00001 / (rp + r00001)) v00010 = round(scale * r00010 / (rp + r00010)) v00011 = round(scale * r00011 / (rp + r00011)) v00100 = round(scale * r00100 / (rp + r00100)) v00101 = round(scale * r00101 / (rp + r00101)) v00110 = round(scale * r00110 / (rp + r00110)) v00111 = round(scale * r00111 / (rp + r00111)) v01000 = round(scale * r01000 / (rp + r01000)) v01001 = round(scale * r01001 / (rp + r01001)) v01010 = round(scale * r01010 / (rp + r01010)) v01011 = round(scale * r01011 / (rp + r01011)) v01100 = round(scale * r01100 / (rp + r01100)) v01101 = round(scale * r01101 / (rp + r01101)) v01110 = round(scale * r01110 / (rp + r01110)) v01111 = round(scale * r01111 / (rp + r01111)) v10000 = round(scale * r10000 / (rp + r10000)) v10001 = round(scale * r10001 / (rp + r10001)) v10010 = round(scale * r10010 / (rp + r10010)) v10011 = round(scale * r10011 / (rp + r10011)) v10100 = round(scale * r10100 / (rp + r10100)) v10101 = round(scale * r10101 / (rp + r10101)) v10110 = round(scale * r10110 / (rp + r10110)) v10111 = round(scale * r10111 / (rp + r10111)) v11000 = round(scale * r11000 / (rp + r11000)) v11001 = round(scale * r11001 / (rp + r11001)) v11010 = round(scale * r11010 / (rp + r11010)) v11011 = round(scale * r11011 / (rp + r11011)) v11100 = round(scale * r11100 / (rp + r11100)) v11101 = round(scale * r11101 / (rp + r11101)) v11110 = round(scale * r11110 / (rp + r11110)) v11111 = round(scale * r11111 / (rp + r11111))

    'calculate ADC voltage readings per button combination t00000 = (v00000 + v00001) / 2 t00001 = (v00001 + v00010) / 2 t00010 = (v00010 + v00011) / 2 t00011 = (v00011 + v00100) / 2 t00100 = (v00100 + v00101) / 2 t00101 = (v00101 + v00110) / 2 t00110 = (v00110 + v00111) / 2 t00111 = (v00111 + v01000) / 2 t01000 = (v01000 + v01001) / 2 t01001 = (v01001 + v01010) / 2 t01010 = (v01010 + v01011) / 2 t01011 = (v01011 + v01100) / 2 t01100 = (v01100 + v01101) / 2 t01101 = (v01101 + v01110) / 2 t01110 = (v01110 + v01111) / 2 t01111 = (v01111 + v10000) / 2 t10000 = (v10000 + v10001) / 2 t10001 = (v10001 + v10010) / 2 t10010 = (v10010 + v10011) / 2 t10011 = (v10011 + v10100) / 2 t10100 = (v10100 + v10101) / 2 t10101 = (v10101 + v10110) / 2 t10110 = (v10110 + v10111) / 2 t10111 = (v10111 + v11000) / 2 t11000 = (v11000 + v11001) / 2 t11001 = (v11001 + v11010) / 2 t11010 = (v11010 + v11011) / 2 t11011 = (v11011 + v11100) / 2 t11100 = (v11100 + v11101) / 2 t11101 = (v11101 + v11110) / 2 t11110 = (v11110 + v11111) / 2 t11111 = (v11111 + 0 ) / 2

    `'---------------------------------
    ' ADC interrupt service routine - runs in background
    '
    adc_isr akpin pin 'let ADC adjust before GIO measurement
    resi3

                rdpin   lev_gio,pin             'read GIO measurement
                wrpin   adc_pin,pin             'connect ADC to pin
                mov     a,#%10000               'search button states by threshold
                mov     b,#%11111
    

    adc_search xor b,a
    altgw b,#thresholds
    getword c
    cmp c,sample_ wc
    if_nc xor b,a
    shr a,#1 wc
    if_nc jmp #adc_search
    resi3 'b=buttons for debounce

                akpin   pin                     'let ADC adjust before pin measurement
                resi3
    
                rdpin   lev_pin,pin             'read pin measurement
                wrpin   adc_vio,pin             'connect ADC to VIO
                mov     a,filter                'if buttons same for five readings, update states_
                rolbyte filter,b,#0
                cmp     a,filter        wz
        if_z    mov     states_,b
                resi3
    
                akpin   pin                     'let ADC adjust before VIO measurement
                resi3
    
                rdpin   lev_vio,pin             'read VIO measurement
                wrpin   adc_gio,pin             'connect ADC to GIO
                sub     lev_vio,lev_gio         'tune measurement period so that
                cmp     lev_vio,target  wcz     'VIO - GIO = target count
        if_ne   sumnc   clocks_,#1
        if_ne   wxpin   clocks_,pin
                sub     lev_pin,lev_gio         'get pin sample
                fges    lev_pin,#0              'stop negative samples
                mov     sample_,lev_pin
                mov     ijmp3,#adc_isr          'loop to start on next interrupt
                reti3
    

    `

    `
    '
    '
    ' Defined data
    '
    target long round(scale)

    clocks_ long round(scale * 1.5)
    sample_ long 0
    states_ long 0

    adc_gio long p_adc_gio | p_count_highs | %00_00000_0
    adc_pin long p_adc_1x | p_count_highs | %00_00000_0
    adc_vio long p_adc_vio | p_count_highs | %00_00000_0

    thresholds word t00000,t00001,t00010,t00011,t00100,t00101,t00110,t00111
    word t01000,t01001,t01010,t01011,t01100,t01101,t01110,t01111
    word t10000,t10001,t10010,t10011,t10100,t10101,t10110,t10111
    word t11000,t11001,t11010,t11011,t11100,t11101,t11110,t11111
    adc_end

    a long 0
    b long 0
    c long 0
    pin long 0
    lev_gio long 0
    lev_pin long 0
    lev_vio long 0
    filter long 0
    `

    split it into sections to see if it fixes the format.

  • Not sure why the format is messing up.

  • You need triple quotes for a code block

  • Luckily, the quote button retrieves the unmangled post source:

    '-------------------------------------------------------------------------------------------------
    
      rp = 2_200.0          'pull-up resistor to VIO (local 3.3V)
      r5 = 1_200.0          '1st button parallel resistor, should be approximately rp
      r4 =   600.0          '2nd button parallel resistor, should be approximately r1 * 2
      r3 =   300.0          '3rd button parallel resistor, should be approximately r2 * 2
      r2 =   150.0          '4th button parallel resistor, should be approximately r3 * 2
      r1 =    75.0          '5th button parallel resistor, should be approximately r4 * 2, connects to GND
    
      scale = 3300.0
    
      'calculate r1..r5 series resistance sums per button combination
      r00000 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
      r00001 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
      r00010 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
      r00011 = 1.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
      r00100 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
      r00101 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
      r00110 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
      r00111 = 1.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
      r01000 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
      r01001 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
      r01010 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
      r01011 = 1.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
      r01100 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
      r01101 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
      r01110 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
      r01111 = 1.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
      r10000 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
      r10001 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
      r10010 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
      r10011 = 0.0 * r5 + 1.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
      r10100 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
      r10101 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
      r10110 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
      r10111 = 0.0 * r5 + 1.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
      r11000 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 1.0 * r1
      r11001 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 1.0 * r2 + 0.0 * r1
      r11010 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 1.0 * r1
      r11011 = 0.0 * r5 + 0.0 * r4 + 1.0 * r3 + 0.0 * r2 + 0.0 * r1
      r11100 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 1.0 * r1
      r11101 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 1.0 * r2 + 0.0 * r1
      r11110 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 1.0 * r1
      r11111 = 0.0 * r5 + 0.0 * r4 + 0.0 * r3 + 0.0 * r2 + 0.0 * r1
    
    
     'calculate ADC voltage readings per button combination
      v00000 = round(scale * r00000 / (rp + r00000))
      v00001 = round(scale * r00001 / (rp + r00001))
      v00010 = round(scale * r00010 / (rp + r00010))
      v00011 = round(scale * r00011 / (rp + r00011))
      v00100 = round(scale * r00100 / (rp + r00100))
      v00101 = round(scale * r00101 / (rp + r00101))
      v00110 = round(scale * r00110 / (rp + r00110))
      v00111 = round(scale * r00111 / (rp + r00111))
      v01000 = round(scale * r01000 / (rp + r01000))
      v01001 = round(scale * r01001 / (rp + r01001))
      v01010 = round(scale * r01010 / (rp + r01010))
      v01011 = round(scale * r01011 / (rp + r01011))
      v01100 = round(scale * r01100 / (rp + r01100))
      v01101 = round(scale * r01101 / (rp + r01101))
      v01110 = round(scale * r01110 / (rp + r01110))
      v01111 = round(scale * r01111 / (rp + r01111))
      v10000 = round(scale * r10000 / (rp + r10000))
      v10001 = round(scale * r10001 / (rp + r10001))
      v10010 = round(scale * r10010 / (rp + r10010))
      v10011 = round(scale * r10011 / (rp + r10011))
      v10100 = round(scale * r10100 / (rp + r10100))
      v10101 = round(scale * r10101 / (rp + r10101))
      v10110 = round(scale * r10110 / (rp + r10110))
      v10111 = round(scale * r10111 / (rp + r10111))
      v11000 = round(scale * r11000 / (rp + r11000))
      v11001 = round(scale * r11001 / (rp + r11001))
      v11010 = round(scale * r11010 / (rp + r11010))
      v11011 = round(scale * r11011 / (rp + r11011))
      v11100 = round(scale * r11100 / (rp + r11100))
      v11101 = round(scale * r11101 / (rp + r11101))
      v11110 = round(scale * r11110 / (rp + r11110))
      v11111 = round(scale * r11111 / (rp + r11111))
    
    
    'calculate ADC voltage readings per button combination
      t00000 = (v00000 + v00001) / 2
      t00001 = (v00001 + v00010) / 2
      t00010 = (v00010 + v00011) / 2
      t00011 = (v00011 + v00100) / 2
      t00100 = (v00100 + v00101) / 2
      t00101 = (v00101 + v00110) / 2
      t00110 = (v00110 + v00111) / 2
      t00111 = (v00111 + v01000) / 2
      t01000 = (v01000 + v01001) / 2
      t01001 = (v01001 + v01010) / 2
      t01010 = (v01010 + v01011) / 2
      t01011 = (v01011 + v01100) / 2
      t01100 = (v01100 + v01101) / 2
      t01101 = (v01101 + v01110) / 2
      t01110 = (v01110 + v01111) / 2
      t01111 = (v01111 + v10000) / 2
      t10000 = (v10000 + v10001) / 2
      t10001 = (v10001 + v10010) / 2
      t10010 = (v10010 + v10011) / 2
      t10011 = (v10011 + v10100) / 2
      t10100 = (v10100 + v10101) / 2
      t10101 = (v10101 + v10110) / 2
      t10110 = (v10110 + v10111) / 2
      t10111 = (v10111 + v11000) / 2
      t11000 = (v11000 + v11001) / 2
      t11001 = (v11001 + v11010) / 2
      t11010 = (v11010 + v11011) / 2
      t11011 = (v11011 + v11100) / 2
      t11100 = (v11100 + v11101) / 2
      t11101 = (v11101 + v11110) / 2
      t11110 = (v11110 + v11111) / 2
      t11111 = (v11111 + 0     ) / 2
    
    '---------------------------------
    ' ADC interrupt service routine - runs in background
    '
    adc_isr         akpin   pin                     'let ADC adjust before GIO measurement
                    resi3
    
                    rdpin   lev_gio,pin             'read GIO measurement
                    wrpin   adc_pin,pin             'connect ADC to pin
                    mov     a,#%10000               'search button states by threshold
                    mov     b,#%11111
    adc_search         xor     b,a
                    altgw   b,#thresholds
                    getword c
                    cmp     c,sample_       wc
            if_nc   xor     b,a
                    shr     a,#1            wc
            if_nc   jmp     #adc_search
                    resi3                           'b=buttons for debounce
    
                    akpin   pin                     'let ADC adjust before pin measurement
                    resi3
    
                    rdpin   lev_pin,pin             'read pin measurement
                    wrpin   adc_vio,pin             'connect ADC to VIO
                    mov     a,filter                'if buttons same for five readings, update states_
                    rolbyte filter,b,#0
                    cmp     a,filter        wz
            if_z    mov     states_,b
                    resi3
    
                    akpin   pin                     'let ADC adjust before VIO measurement
                    resi3
    
                    rdpin   lev_vio,pin             'read VIO measurement
                    wrpin   adc_gio,pin             'connect ADC to GIO
                    sub     lev_vio,lev_gio         'tune measurement period so that
                    cmp     lev_vio,target  wcz     'VIO - GIO = target count
            if_ne   sumnc   clocks_,#1
            if_ne   wxpin   clocks_,pin
                    sub     lev_pin,lev_gio         'get pin sample
                    fges    lev_pin,#0              'stop negative samples
                    mov     sample_,lev_pin
                    mov     ijmp3,#adc_isr          'loop to start on next interrupt
                    reti3
    
    `
    '
    '
    ' Defined data
    '
    target          long    round(scale)
    
    clocks_         long    round(scale * 1.5)
    sample_         long    0
    states_         long    0
    
    adc_gio         long    p_adc_gio | p_count_highs | %00_00000_0
    adc_pin         long    p_adc_1x  | p_count_highs | %00_00000_0
    adc_vio         long    p_adc_vio | p_count_highs | %00_00000_0
    
    thresholds      word    t00000,t00001,t00010,t00011,t00100,t00101,t00110,t00111
                    word    t01000,t01001,t01010,t01011,t01100,t01101,t01110,t01111
                    word    t10000,t10001,t10010,t10011,t10100,t10101,t10110,t10111
                    word    t11000,t11001,t11010,t11011,t11100,t11101,t11110,t11111
    adc_end
    
    a               long    0
    b               long    0
    c               long    0
    pin             long    0
    lev_gio         long    0
    lev_pin         long    0
    lev_vio         long    0
    filter          long    0
    
  • Also, how often should this run?

  • BaggersBaggers Posts: 3,019
    edited 2021-10-17 19:27

    It's in the interrupts, at the 3rd level, and yeah sorry, I forgot to add that bit of setup

    Clock was at 70Mhz too.

    '
    ' ADC program setup
    '
                  rdlong  pin,ptra[SINGLE_BUTTON_PIN] 'pin
                  fltl    pin                     'set pin to ADC mode + count highs
                  wrpin   adc_gio,pin
                  wxpin   clocks_,pin
                  wypin   #0,pin
                  drvl    pin
    '
                  mov     ijmp3,#adc_isr          'set interrupt jump
                  mov     a,pin                   'set ADC pin IN-rise event
                  or      a,#%001<<6
                  setse1  a
                  setint3 #event_se1              'enable interrupt on event
    
  • @Baggers thanks! Will have to see where that can be ideally integrated.

  • Good luck :D holler if you need anything, but I reckon you've got this. :D

Sign In or Register to comment.