Propeller Signal Generator

Ahle2Ahle2 Posts: 906
edited November 2013 in Propeller 1 Vote Up0Vote Down
Have a look in the OBEX for the latest version!
http://obex.parallax.com/objects/872/

Version 1.2 features:
* Runs in a single cog
* Uses "duty dac"
* 1.25 MHz sample rate
* 6 waveform types (Saw, Triangle, Square, Noise, Sine, User)
* High resolution pulse width
* Outputs both normal and inverted signal at the same time
* Synchronization output on extra pin
* Signal can be damped in steps of 6 dB
* All parameters can be changed on the fly




Original first post below
I needed a signal generator that had a small footprint and a high sample rate; So I made one!

Features:
* Uses "duty dac"
* 600 kHz sample rate
* 4 waveform types (Saw, Triangle, Square, Noise)
* High resolution pulse width
* Outputs both normal and inverted signal at the same time
* Signal can be damped in steps of 6 dB
* All parameters can be changed on the fly
SIDcog - The sound of the Commodore 64 in a single cog: Thread, OBEX, SIDcogMedlay.mp3
AYcog - An emulation of the AY3-8910 / YM2149F PSG: Thread, OBEX
SNEcog - An emulation of the SN76489 PSG(and variants): Thread, OBEX
Propeller chiptune player: Thread
«13

Comments

  • 78 Comments sorted by Date Added Votes
  • groggorygroggory Posts: 205
    edited June 2012 Vote Up0Vote Down
    Fantastic! My hardware signal generator has been glitching at the up and down swings of the square waves.

    Propeller to the rescue!
  • Dr_AculaDr_Acula Posts: 5,482
    edited June 2012 Vote Up0Vote Down
    Very nice. The heart of a synthesizer in software. Amazingly short code. When I get a moment I might see if I can turn this into an app for the touchscreen. 4 switches square, sine, tri, noise. Slider for frequency. Switches for x10, x100, x1000. Maybe input an exact frequency via a numeric screen.
    Answers: 1) A quadcopter. 2) Very high. 3) The internet. 4) A lot. 5) No.
  • Ahle2Ahle2 Posts: 906
    edited June 2012 Vote Up0Vote Down
    @Phil Pilgrim
    I can do all kinds of mathematical calculations on jitter, "frequency exactness", linearity, resolution, SNR... etc
    But I would like to have some real measurments on the performance..... pretty please! :)
    You have got all this equipment to do good measurements (and the knowledge of course)

    Many of these unknowns depends on the analog output stage... RC filter, OP... etc... etc...
    And of course, the "duty DAC" is FAAAAR from good enough for high bandwidth signals. And of course, there's all kinds of "digital artifacts" generated inside the Prop. But let's say that we would want "optimal" performance for audio stuff. Then we would like to have a low pass filter with an extremely steep curve (48 dB or more) with a cut off of ~20 kHz to get rid of "duty noise". We would also like to have a high performance OP. and overall good components.

    I want measurments of how well the "optimal" duty DAC circuit performs in combination with my PSG:
    * Resolution for audio signals
    * SNR (different pins and cogs... etc)
    * Jitter
    * Linearity
    * Frequency exactness (in lack of better words)
    *

    (BTW, I think I can reach a sample rate of around 1 Mhz (80 Mhz prop) with some optimisations)
    SIDcog - The sound of the Commodore 64 in a single cog: Thread, OBEX, SIDcogMedlay.mp3
    AYcog - An emulation of the AY3-8910 / YM2149F PSG: Thread, OBEX
    SNEcog - An emulation of the SN76489 PSG(and variants): Thread, OBEX
    Propeller chiptune player: Thread
  • pik33pik33 Posts: 776
    edited June 2012 Vote Up0Vote Down
    The more sample rate, the less bit resolution of signal.

    I am now experimenting with sample player. dithered, non dithered, noise shaped etc. Normal "duty DAC" gives 1812 clock cycles between two samples @44.1 kHz, and it means about 10bit DAC
    And it means that lower bits of 16-bit signal causes peaks here and there - in accoustic band. All of this interferes with Propeller's internal work currents, so this noise depends on what cog is used and don't know what else. I tested my sample player without dithering with coginit instead of cognew, every cog gives different result. The best was using cog0 with playing routine and high numbered cogs for background work.

    One remedium for it is this high frequency - 1 MHz in reality - white noise dither

    Maybe, as someone wrote in my "sample player" topic, noise shaping and oversampling can give better results.
    Another idea I want to try is using video generator for audio. This can be clocked with pll - something about 200 MHz instead of 80 MHz - I have to try it.
  • Ahle2Ahle2 Posts: 906
    edited June 2012 Vote Up0Vote Down
    What you say is correct, but that's "just" theory. Real performance doesn't always match calculated performance. That's the reason I would like real measurments! :)

    Btw, using the vide generator for audio has been done before and the bandwidth is great, but the resolution is.... crap (8 bits at most). Maybe we could use two cogs/video generators, one taking care of the 8 MSBs and the other taking care of the LSBs?! Of course 16 pins will be needed and it might be hard to synchronize the two video generators. Just a thought!
    SIDcog - The sound of the Commodore 64 in a single cog: Thread, OBEX, SIDcogMedlay.mp3
    AYcog - An emulation of the AY3-8910 / YM2149F PSG: Thread, OBEX
    SNEcog - An emulation of the SN76489 PSG(and variants): Thread, OBEX
    Propeller chiptune player: Thread
  • pik33pik33 Posts: 776
    edited June 2012 Vote Up0Vote Down
    Ahle2 wrote: »

    Btw, using the vide generator for audio has been done before and the bandwidth is great, but the resolution is.... crap (8 bits at most).

    Time to run bst and start testing :)
  • pik33pik33 Posts: 776
    edited June 2012 Vote Up0Vote Down
    Quick, made in 20 minutes,dirty and buggy working proof of concept - 12bit/44100 1-channel dac with video generator. 2 channels will be possible.
    
                            org     0
    
    ' //////////////////////Initialization/////////////////////////////////////////////////////////////////////////////////////////
    
    init
                            mov     dira,                      ditherOutputMask
                            mov     ctra,#0
                            movi    ctra,#%0_00001_111         'pll div 1
                            mov     frqa,frqa_val               '
                            mov     vscl,vscl_val              'init video generator
                            mov     vcfg,vcfg_val
                            mov     bufptr2,par
    
    
    loop                    mov     ptr,bufptr
                            add     ptr,bufcnt         'pointer to next sample
                            rdword  lsample,ptr        'get left sample
                            add     lsample,offset     'convert to unsigned
                            add     ptr, #2
                            rdword  rsample,ptr        
                            and     lsample,ffff
                            add     rsample,offset
                            and     rsample,ffff
                            add     bufcnt,#4
                            and     bufcnt,bufmask
                            wrlong  bufcnt,bufptr2
                            mov     t3,rsample
                            shr     t3,#4
                            and     t3,mask5
    
                            mov     t4,ffffffff
                            shr     t4,t3
    
                            mov     t1,rsample
    
                            shr     t1,#9
                            add     t1,#1
                            mov     t2,#129
                            sub     t2,t1
                            shl     t1,#5
                            shl     t2,#5
                            add     t2,vscl_val0
                            add     t1,vscl_val0
                            mov     outa, zero
                            mov     vscl,t1
    
    p11                     waitvid zero,zero
                            mov     vscl,vscl_val
                            waitvid ffffffff,t4
                            mov vscl,t2
    p12                     waitvid ffffffff,ffffffff
                            mov     outa,mask1
                            jmp     #loop
    
    
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    '                       Data
    ' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    
    
    
    leftTaps                long    $A4_00_00_80                                   ' Left LFSR taps.
    rightTaps               long    $80_A0_10_00                                   ' Right LFSR taps.
    
    leftLFSR                long    1                                              ' Initial value.
    rightLFSR               long    1                                              ' Initial value.
    
    ' //////////////////////Configuration Settings/////////////////////////////////////////////////////////////////////////////////
    
    ditherLeftCounterSetup  long    0
    ditherRightCounterSetup long    0
    ditherOutputMask        long    0
    
    leftDitherShift         long    0
    rightDitherShift        long    0
    
    ' //////////////////////Addresses//////////////////////////////////////////////////////////////////////////////////////////////
    
    ditherLeftAddress       long    0
    ditherRightAddress      long    0
    
    ' //////////////////////Run Time Variables/////////////////////////////////////////////////////////////////////////////////////
    
    lsample    long 0
    rsample    long 0
    ls2 long 0
    rs2 long 0
    bufmask    long %0000_0000_0000_0000_0000_0111_1111_1111
    ptr        long 0
    temp long 0
    
    bufptr  long 0
    bufcnt  long 0
    bufptr2 long 0
    
    offset  long $8000
    ffff    long %1111_1111_1111_1111
    mask1 long  %0000_0000_0000_0000_0000_1100_0000_0000
    mask5 long  31
    
    ffffffff long $ffffffff
    
    zero long 0
    vscl_val                long    $00001020       '1 clock/pixel,    32 clock/frame, std vscl for display
    vscl_val0   long $00001000
    t1 long 0
    t2 long 0
    t3 long 0
    t4 long 0
    
    
    vcfg_val long $200002ff
    
    frqa_val long $25000000
    
                            fit     496
    
  • jmgjmg Posts: 10,455
    edited June 2012 Vote Up0Vote Down
    What about the video pathway, driving a 'proper' Stereo 24b DAC, they are close to $1, and sidestep all the cross-talk and patches.. ?
  • pik33pik33 Posts: 776
    edited June 2012 Vote Up0Vote Down
    Yes, of course, but...

    (1) this is another chip
    (2) $1? Where to buy???
    (3) they are not suitable for a signal generator described in this topic - too low frequency
  • Mark_TMark_T Posts: 1,621
    edited June 2012 Vote Up0Vote Down
    pik33 wrote: »
    Yes, of course, but...

    (1) this is another chip
    (2) $1? Where to buy???
    (3) they are not suitable for a signal generator described in this topic - too low frequency

    Wolfson Microelectronics WM8762, WM8759, WM8766... I2S bus, 24 bit stereo sigma-delta, upto 192kHz sample rate. Available from Farnell.

    [ Also don't forget R-2R resistor ladder converter! ]
  • jmgjmg Posts: 10,455
    edited June 2012 Vote Up0Vote Down
    pik33 wrote: »
    Yes, of course, but...

    (1) this is another chip

    Sure, but roughly the same incremental cost as a single COG.

    (2) $1? Where to buy???

    AK4386ETP-E2 at digikey is 52c/1k and 94c/100+
    (3) they are not suitable for a signal generator described in this topic - too low frequency

    No problem - For higher frequencies, you can still use any prop pin you like.
    For square wave clocks, direct connect would likely be best.

    At Audio frequencies, which is where a lot of the focus is, then the cheap DAC gives far better noise/distortion, and can use the Sine LUT in Prop, for low distortion sine.
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 21,226
    edited June 2012 Vote Up0Vote Down
    Ahle2 wrote:
    But I would like to have some real measurments on the performance..... pretty please!
    I really wish I could help, but my spectrum analyzer doesn't work at audio frequencies -- at least not those below 9 KHz -- and it's pretty dodgy until you get to RF frequencies. 'Always happy to analyze RF for people, though. :)

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • Ahle2Ahle2 Posts: 906
    edited June 2012 Vote Up0Vote Down
    New version of "Propeller Signal Generator" posted in OBEX!
    http://obex.parallax.com/objects/872/

    * Sample rate increased to 1.25 MHz (Because I hate jitter and aliasing)
    * Code size decreased by 10% (It's just 39 rows of assembly now)
    SIDcog - The sound of the Commodore 64 in a single cog: Thread, OBEX, SIDcogMedlay.mp3
    AYcog - An emulation of the AY3-8910 / YM2149F PSG: Thread, OBEX
    SNEcog - An emulation of the SN76489 PSG(and variants): Thread, OBEX
    Propeller chiptune player: Thread
  • onewheeltomonewheeltom Posts: 40
    edited June 2012 Vote Up0Vote Down
    I presume it would not be difficult to add knobs and frequency range switches... rotary encoders would probably be simpler as pots would require additional circuitry. Or not?

    --tom
    Ahle2 wrote: »
    New version of "Propeller Signal Generator" posted in OBEX!
    http://obex.parallax.com/objects/872/

    * Sample rate increased to 1.25 MHz (Because I hate jitter and aliasing)
    * Code size decreased by 10% (It's just 39 rows of assembly now)
  • groggorygroggory Posts: 205
    edited June 2012 Vote Up0Vote Down
    I presume it would not be difficult to add knobs and frequency range switches... rotary encoders would probably be simpler as pots would require additional circuitry. Or not?

    --tom

    That all depends on your preference. A pot would be super simple using this circuit...

    http://www.rayslogic.com/propeller/programming/adc.htm
    TypicalAdcCircuit.png

    Your input signal would be the wiper on a potentiometer.

    You'd sample the potentiometer and equate various voltage values as settings for your home brew signal generator.

    Personally, I'd prefer to use a handful of buttons plus the rotary encoder, but the pot method is super simple.
  • g3cwig3cwi Posts: 262
    edited June 2012 Vote Up0Vote Down
    I really wish I could help, but my spectrum analyzer doesn't work at audio frequencies

    Try this: http://www.qsl.net/dl4yhf/spectra1.html

    It is excellent.

    Regards

    Richard
  • cavelambcavelamb Posts: 645
    edited June 2012 Vote Up0Vote Down
    groggory wrote: »
    That all depends on your preference. A pot would be super simple using this circuit...

    http://www.rayslogic.com/propeller/programming/adc.htm
    TypicalAdcCircuit.png

    Your input signal would be the wiper on a potentiometer.

    You'd sample the potentiometer and equate various voltage values as settings for your home brew signal generator.

    Personally, I'd prefer to use a handful of buttons plus the rotary encoder, but the pot method is super simple.

    Guess I'm olde fashioned, I still like the smooth response of a real knob.

    Question: the 1n notation on the caps?
  • groggorygroggory Posts: 205
    edited June 2012 Vote Up0Vote Down
    cavelamb wrote: »
    Guess I'm olde fashioned, I still like the smooth response of a real knob.

    Question: the 1n notation on the caps?

    1n = 1 nanofarad = 1 x 10^-9 F = .001 x 10^-6 F = .001 uF

    I like the feel of real knobs too. I hear ya.
  • onewheeltomonewheeltom Posts: 40
    edited June 2012 Vote Up0Vote Down
    Detents can be removed from encoders :-)

    I've been thinking of a project with, lets say, 8 knobs that will control various parameters of the software running in the Prop.

    The RC circuit takes 2 pins, which may not be a big deal.

    Excluding preferences for feel, to interface these 8 knobs (pots or encoders) with the Prop, which circuit would have the fewest number of components?

    --tom
    groggory wrote: »
    1n = 1 nanofarad = 1 x 10^-9 F = .001 x 10^-6 F = .001 uF

    I like the feel of real knobs too. I hear ya.
  • groggorygroggory Posts: 205
    edited June 2012 Vote Up0Vote Down
    If you're going to use 8 knobs, I'd go with 8 pots + an 8 channel ADC such as the MCP3208.
    Detents can be removed from encoders :-)

    I've been thinking of a project with, lets say, 8 knobs that will control various parameters of the software running in the Prop.

    The RC circuit takes 2 pins, which may not be a big deal.

    Excluding preferences for feel, to interface these 8 knobs (pots or encoders) with the Prop, which circuit would have the fewest number of components?

    --tom
  • Ahle2Ahle2 Posts: 906
    edited June 2012 Vote Up0Vote Down
    I have been experimenting with the signal generator using different Propeller boards connected to my scope.
    And I must warn that the audio out port on the Propeller Demo Board isn't an option at all. Even after some modifications of the RC filter the signal still is severely "distorted".
    It seems like the OP/headphone circuit has a very nonlinear frequency response. I would guess that some kind of loudness filter is applied.
    SIDcog - The sound of the Commodore 64 in a single cog: Thread, OBEX, SIDcogMedlay.mp3
    AYcog - An emulation of the AY3-8910 / YM2149F PSG: Thread, OBEX
    SNEcog - An emulation of the SN76489 PSG(and variants): Thread, OBEX
    Propeller chiptune player: Thread
  • cavelambcavelamb Posts: 645
    edited June 2012 Vote Up0Vote Down
    groggory wrote: »
    1n = 1 nanofarad = 1 x 10^-9 F = .001 x 10^-6 F = .001 uF

    I like the feel of real knobs too. I hear ya.

    So what does a 1 nano farad cap look like?
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 21,226
    edited June 2012 Vote Up0Vote Down
    cavelamb wrote:
    So what does a 1 nano farad cap look like?
    By an extraordinary set of coincidences and planetary alignments, 1nF caps look identical to both 0.001uF caps and 1000pF caps!

    -Phil
    “Perfection is achieved not when there is nothing more to add, but when there is nothing left to take away. -Antoine de Saint-Exupery
  • Dr_AculaDr_Acula Posts: 5,482
    edited June 2012 Vote Up0Vote Down
    By an extraordinary set of coincidences and planetary alignments, 1nF caps look identical to both 0.001uF caps and 1000pF caps!

    Goodness me!

    *rummages through parts drawers*

    He's right, by jove!
    Answers: 1) A quadcopter. 2) Very high. 3) The internet. 4) A lot. 5) No.
  • Cluso99Cluso99 Posts: 12,840
    edited June 2012 Vote Up0Vote Down
    By an extraordinary set of coincidences and planetary alignments, 1nF caps look identical to both 0.001uF caps and 1000pF caps!

    -Phil
    My mate's wife used to call them little pillows. They come in a few standard colors, particularly yellow and green. Of course, the smt ones come in various sizes too... 1206, 0805, 0603...
    My Prop boards: P8XBlade2, RamBlade, CpuBlade, TriBlade
    Prop OS (also see Sphinx, PropDos, PropCmd, Spinix)
    Website: www.clusos.com
    Prop Tools (Index) , Emulators (Index) , ZiCog (Z80)
  • Dr_AculaDr_Acula Posts: 5,482
    edited June 2012 Vote Up0Vote Down
    So what does a 1 nano farad cap look like?

    I've got drawers full of the brown ones http://www.futurlec.com/Capacitors/C001UC.shtml but my favorites are the green shiny ones http://www.futurlec.com/Capacitors/C001U250M.shtml

    @Cluso, wasn't there a discussion a while back about how the propeller demo board has the wrong filter caps? http://elmicro.com/files/parallax/propdemod_schematic.pdf

    10nf and 10k gives 1591hz according to http://sim.okawa-denshi.jp/en/CRtool.php Would 10nf and 1k be better?
    Answers: 1) A quadcopter. 2) Very high. 3) The internet. 4) A lot. 5) No.
  • onewheeltomonewheeltom Posts: 40
    edited June 2012 Vote Up0Vote Down
    Which boards provide the best results?

    --tom
    Ahle2 wrote: »
    I have been experimenting with the signal generator using different Propeller boards connected to my scope.
    And I must warn that the audio out port on the Propeller Demo Board isn't an option at all. Even after some modifications of the RC filter the signal still is severely "distorted".
    It seems like the OP/headphone circuit has a very nonlinear frequency response. I would guess that some kind of loudness filter is applied.
  • Dr_AculaDr_Acula Posts: 5,482
    edited June 2012 Vote Up0Vote Down
    Hi Ahle2,

    I added a front end to your signal generator. Knobs, switches etc all work with a touchscreen. You can dial up approx the right frequency with the slider knob, then adjust with the +1 and -1 buttons for the exact frequency.
    CON
      _clkmode      = xtal1 + pll16x                        ' use crystal x 16
      _xinfreq      = 5_000_000
       
    OBJ
      tch:           "Touch"                                 ' touchscreen driver
    '  F          : "FloatMath"                 'From Parallax Inc. v1.0
      Q          : "SPIN_TrigPack"             'v2.0 CompElit Ltd.
        psg : "PropellerSignalGenerator"                    ' thanks to Ahle2
    
    VAR
    
    
    PUB Main 
      tch.BeginProgram                                        
      Function
      tch.SetWarmBoot                                           ' clears screen, sets a warm boot and reboots
    
    PUB Function | xval,yval,org_x,org_y,pointx,pointy,r,theta,a,switchx,switchy,frequency,font,range,slider,xslider,yslider,waveform
        psg.start(21, 23)                                   ' two audio pins (not next to each other so less crosstalk)
        frequency := 440
        range := 1                                          ' x10, x100 etc
        slider := 44                                        ' 0-255
        xslider := 26                                       ' position of the slider
        yslider := 144
        waveform := 21                                       ' waveform SAW = 18, TRIANGLE = 21, SQUARE = 24, NOISE = 27,                                    
        tch.ClearRam                                        ' clear all but file 0 and 1
        tch.StringDim(10)                                   ' file 2 = strings if needed
        tch.SDBMPtoRam(string("function.bmp"))              ' file 3
        tch.SDBMPtoRam(string("rot1.bmp"))                  ' file 4
        tch.SDBMPtoRam(string("rot2.bmp"))                  ' file 5
        tch.SDBMPtoRam(string("rot3.bmp"))                  ' file 6
        tch.SDBMPtoRam(string("rot4.bmp"))                  ' file 7
        font := tch.Loadfont(string("DSdigGr.ifn"))         ' file 8
        tch.SDBMPtoRam(string("SlideP.bmp"))                ' file 9 slider
        tch.SDBMPtoRam(string("synknbp.bmp"))               ' file 10 slider knob
        tch.SDBMPtoRam(string("synoffP.bmp"))               ' file 11 switch off
        tch.SDBMPtoRam(string("synonP.bmp"))                ' file 12 slider knob
        tch.DrawBMPRam(3,0,0)                               ' draw file 3
        DrawSlider(xslider,yslider,slider,9)   
        LCDPrintFrequency(frequency,font)                   ' clear the little LCD display and print frequency
        RedrawSwitches(waveform)                            ' redraw the switches
        switchx := 138                                      ' centre of the switch, not the top left
        switchy := 171                                      ' switch bitmap is 60x60
        tch.DrawBMPRam(4,switchx-30,switchy-30)             ' draw file 4
        tch.SelectSPIGroup                                  ' talk to the spi touchscreen
        repeat
          yval := tch.TouchYPercent                         ' decode yval 0-100%               
          xval := tch.TouchXPercent                         ' decode xval 0-100%
          if (xval <> 255)  and (yval <> 255)               ' valid keypress
             xval := (xval*24)/10                           ' 0-240, use portrait mode 
             yval := (yval*32)/10                           ' 0-320
             'tch.hex(xval,2)
             'tch.hex(yval,2)
             org_x := q.Qval(switchx)                       ' origin x of the switch
             org_y := q.Qval(switchy)                       ' origin y
             pointx := q.Qval(xval)                         ' point touched
             pointy := q.Qval(yval)                         ' point touched
             r := q.Qradius(pointx - org_x, pointy - org_y)
             'tch.text(Q.QvalToStr(r))                      ' debugging
             theta := Q.Deg_ATAN2(pointx - org_x, org_y - pointy)     ' pointy and orgy swapped as 0,0 is top left of the screenpolar coordinates with correct sign
             'tch.text(Q.QvalToStr(theta))  
             theta += q.Qval(180)                           ' rotate 180 degrees and remove negative numbers, 0=9 o'clock, 90=6 o'clock, 180 = 3 o'clock, 270 = 12 o'clock
             'tch.hex(r >> 16,2)
             if (r >> 16) < 47                              ' touch close to the switch
               case (theta >> 16)
                 0..90: tch.DrawBMPRam(4,switchx-30,switchy-30)                  ' draw switch position 1
                        range := 1
                 91..180:tch.DrawBMPRam(7,switchx-30,switchy-30)                 ' draw switch position 4
                        range := 1000
                 181..270:tch.DrawBMPRam(6,switchx-30,switchy-30)                ' draw switch position 3
                        range := 100
                 271..359:tch.DrawBMPRam(5,switchx-30,switchy-30)                ' draw switch position 2
                        range := 10
               frequency := RecalcFrequency(slider,range,frequency,font,waveform)        ' redraw the display
             'tch.text(Q.QvalToStr(theta))                  ' debugging
    
             if xval >60 and xval <119 and yval >220 and yval <250     ' -1 frequency button
               frequency +=1
               LCDPrintFrequency(frequency,font)
             if xval >120 and xval <180 and yval >220 and yval <250    ' +1 frequency button      
               frequency -=1
               LCDPrintFrequency(frequency,font)
             if xval > xslider and xval <60 and yval >yslider and yval <212      ' slider 26,144
               slider := yval - yslider                                          ' position on slider
               slider := slider * 256                                            ' 69 pixels high convert to 0-255
               slider := slider / 69
               if slider > 255
                 slider := 255
               if slider < 0
                 slider := 0
               tch.SelectMemGroup
               DrawSlider(xslider,yslider,slider,9)                                   ' redraw this slider
               frequency := RecalcFrequency(slider,range,frequency,font,waveform)             ' redraw the display
             if yval >58 and yval < 114                     ' one of the 4 switches
               case xval
                 25..59:waveform := 18                      ' sawtooth
                 77..110:waveform := 21                     ' triangle
                 129..162:waveform := 24                    ' square
                 181..214:waveform := 27                    ' noise
               RecalcFrequency(slider,range,frequency,font,waveform) ' refresh display and output sound
               RedrawSwitches(waveform)                                       
             if xval >190 and xval <240 and yval>0 and yval <40 ' off button
               return
             
             tch.pause1ms(100) ' debounce delay  
             tch.SelectSPIGroup
    
    PUB DrawSlider(x,y,value,filen)                              ' value is 0-255. assumes bitmaps in ram
        tch.DrawBMPRam(filen,x,y)                               ' draw background
        tch.DrawBMPRam(filen+1,x+5,y+((value*100)/450))           ' draw the knob
    
    PUB LCDPrintFrequency(frequency,font)
         tch.ClearRectangle(41,265,197,307,tch.GetBackFontColor) ' clear an area the same color as the font background   
         tch.SetCursor(46,267)
         tch.StringStr(0,frequency)                    ' store frequency to string zero
         tch.StringPrint(font,0)
    
    PUB RecalcFrequency(slider,range,frequency,font,waveform)
        frequency := slider * 4 * range        ' slider 0-255, first range is 0-1000 Hz
        LCDPrintFrequency(frequency,font)
        if waveform <> 24                                   ' not square
          psg.setParameters(waveform, frequency, 1, 0)      ' output the sound
        else
          psg.setParameters(waveform, frequency, 1, 1<<31)  ' square 50%   
        result := frequency
    
    PUB RedrawSwitches(waveform) ' SAW = 18, TRIANGLE = 21, SQUARE = 24, NOISE = 27
        tch.SelectMemGroup
        tch.DrawBMPRam(11,25,59) ' draw all switches off first
        tch.DrawBMPRam(11,77,59)    
        tch.DrawBMPRam(11,129,59)
        tch.DrawBMPRam(11,181,59)
        case waveform
          18:tch.DrawBMPRam(12,25,59)     ' switch on
          21:tch.DrawBMPRam(12,77,59)
          24:tch.DrawBMPRam(12,129,59)
          27:tch.DrawBMPRam(12,181,59)   
    
    640 x 480 - 59K
    Answers: 1) A quadcopter. 2) Very high. 3) The internet. 4) A lot. 5) No.
  • Ahle2Ahle2 Posts: 906
    edited June 2012 Vote Up0Vote Down
    Which boards provide the best results?
    My own!

    A modified C3 or El Jugador gives a much better result than a modified Demo Board.
    SIDcog - The sound of the Commodore 64 in a single cog: Thread, OBEX, SIDcogMedlay.mp3
    AYcog - An emulation of the AY3-8910 / YM2149F PSG: Thread, OBEX
    SNEcog - An emulation of the SN76489 PSG(and variants): Thread, OBEX
    Propeller chiptune player: Thread
  • Ahle2Ahle2 Posts: 906
    edited June 2012 Vote Up0Vote Down
    @Dr_Acula
    That's extremely cool, I wish I had your board to play around with!
    SIDcog - The sound of the Commodore 64 in a single cog: Thread, OBEX, SIDcogMedlay.mp3
    AYcog - An emulation of the AY3-8910 / YM2149F PSG: Thread, OBEX
    SNEcog - An emulation of the SN76489 PSG(and variants): Thread, OBEX
    Propeller chiptune player: Thread
Sign In or Register to comment.