Shop OBEX P1 Docs P2 Docs Learn Events
Fake Microphone input for QuickStart board — Parallax Forums

Fake Microphone input for QuickStart board

mstrammstram Posts: 49
edited 2017-10-09 23:56 in Propeller 1
In this thread Beau Schwabe posted code for a Phase modulator for the Demo board that digitizes the microphone, then "modulates the samples over the desired synthesized frequency generated on CTRB."

I'm using a Quickstart board though, and therefore no real microphone so .....

I tried to modify the code, adding a "fakeMic" routine that would supply the microphone pin (9 ??) with the
samples from an 8bit /11_025 sample rate .wav file.

But I'm just getting "white noise" output.

The fakeMic is started in a new cog :
cognew(fakeMic,@fakeMicStack)

I changed the "bits" constant from 11 to 8, but it still doesn't work.

I also tried the "fakeMic" routine with both a delay (simulating an 11K sample rate) and without, and both just yield
"noise".

Is the "fakeMic" spin code too slow ?

Mike
CON
 SampRate = 11_025
PUB fakeMic |p,time,x
    dira[9]~~ 'pin the ADC routine thinks the microphone is connected to (demo board)
    x := clkfreq / SampRate
  
  repeat
     p := @wav1 + 44
    time := cnt
    repeat while p++ < @wav1_end    
       outa[9] := p
    '  wait to simulate sample rate    
     waitcnt(time += x)
DAT
 wav1 byte
 File "be_back.wav"
wav1_end byte 0

Comments

  • outa[9] := p

    This just outputs the LSB of the referred-to byte. That's why you're hearing white noise. You need to configure a counter in DUTY mode that outputs to pin 9. Then write the waveform value to frqx.

    (You may need to use a different output pin, along with an RC filter between that and pin 9. I've forgotten how the mic input on the demo board is wired.)

    -Phil
  • mstrammstram Posts: 49
    edited 2017-10-09 20:45
    Ok I changed the code to this, still just noise :
    PUB fakeMic |p,time,x,txpin
    
        txpin :=  9
        dira[txpin]~~ 'pin the ADC routine thinks the microphone is connected to 
    
        CTRA := %00110  << 26 | txpin   'Duty single ended mode 
    
       x := clkfreq / SampRate
      
      repeat
         p := @wav1 + 44
        time := cnt
    
        repeat while p++ < @wav1_end    
           FRQA := byte[p]
        '  wait to simulate sample rate    
         waitcnt(time += x)
    
  • AribaAriba Posts: 2,690
    edited 2017-10-09 23:16
    Here is the code modified with a DUTY output of the samples (untested).
    CON
     SampRate = 11_025
    PUB fakeMic |p,time,x
        ctra := %00110 << 26 + 9       'DUTY output on pin 9
        dira[9]~~ 'pin the ADC routine thinks the microphone is connected to (demo board)
        x := clkfreq / SampRate
      
      repeat
         p := @wav1 + 44
        time := cnt
        repeat while p++ < @wav1_end    
           frqa := byte[p] << 24        'write sample to DUTY modulator
        '  wait to simulate sample rate    
         waitcnt(time += x)
    DAT
     wav1 byte
     File "be_back.wav"
    wav1_end byte 0
    

    Andy
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2017-10-09 23:11
    'Just looked at the Demo Board schematic. You won't be able to use P9 as an output. That will only produce a random sequence of ones and zeroes, leading to more white noise.

    What you need to do is pry the microphone out of its socket. Then connect a different port pin (e.g. P7) to an RC lowpass filter. The counter's DUTY mode output should be directed to this pin. The output of the RC filter should connect to the lower pin of the mic socket. This can be done via a 1/8 watt resistor, since it has skinny leads that will fit the socket. The other end of the resistor should be doubled over and pinched tight so it can make contact with the RC filter in the breadboard area.

    -Phil
  • AribaAriba Posts: 2,690
    edited 2017-10-09 23:17
    Try it with:
        FRQA := byte[p] << 24
    
    the 8 bit sample must be at the top 8 bits of FRQA. Sorry - I have edited that in my previous post.

    @Phil
    He uses a Quickstart board not a Demoboard.

    Andy
  • PublisonPublison Posts: 12,366
    edited 2017-10-09 23:45
    @Phil
    He uses a Quickstart board not a Demoboard.
    Andy

    The first post states it is a demo board. I can't find that it was changed to a QuickStart?
  • >The first post states it is a demo board. I can't find that it was changed to a QuickStart?

    I'm using a quickstart, which I put in the thread title.

    I wrote in the OP that the program had been written for the demoboard ;)

    Sorry for the confusion.
  • @phil
    >What you need to do is pry the microphone out of its socket.

    If I had an actual Demoboard, I wouldn't need a "fakeMic" ;)
  • Okay, 'got it. Make sure you've soldered R17, R18, C15, and C16 to the board. You still can't output to P8 or P9, since they are part of the ADC circuitry. You will have to output your DUTY mode counter to another pin, then connect that pin to the input terminal of J8.

    -Phil
  • Solder r17, r18,c15 c16?

    Where are you getting those from ?

    The "ADC circuitry" is just the prop itself. (doing Sigma-Delta ADC) per the app note : AN001-P8X32ACounters-v2.0.pdf (pg 17 ... which looks very similar to Beau's code (maybe he wrote *that* too ?)

    >You still can't output to P8 or P9, since they are part of the ADC circuitry. You >will have to output your DUTY mode counter to another pin, then connect that >pin to the input terminal of J8.

    Output from one COG to the same pin another COG is reading was going to be the subject of another thread, or maybe a question I was going to ask in my OP.

    But I did some very slow tests with writing / reading to the same pin from two cogs and it seemed to be working.

    If that is the problem, then maybe that's why this is not working ?

    @ariba -
    FRQA := byte[p] << 24
    
    wasn't the "magic fix" I needed ;). At least it didn't fix everything (it may very well be needed, I'll defer to your expertise, but it seems like still other issues are still yet to be solved.

    Mike
  • mstram wrote:
    Solder r17, r18,c15 c16? Where are you getting those from ?
    Those are the parts of the ADC circuitry that Parallax does not provide on the Quickstart board. You need to source them and solder them on.
    Output from one COG to the same pin another COG is reading was going to be the subject of another thread, or maybe a question I was going to ask in my OP.
    You can do that, but not here. The reason is that you have to convert from digital to analog, before you can convert back to digital. That series resistor from the input pin of J8 is important.

    I assume, when you mean "fake the microphone input" that that's what you want to do. But if you just want to play a tune from your wave file, there are easier ways to go about it, since it's already in digital format.

    -Phil
  • AribaAriba Posts: 2,690
    The DUTY output of a counter is somewhat similar to a bitstream generated by the SigmaDelta ADC, so if you put this DUTY output from the sample player to the Pin on which the Modulaterobject expects the ADC input, it should work without any resistors and capacitors.

    But it makes not much sense to go over a DAC -> ADC on a Pin just to use a premade object. If you look how the Phase is modulated in Beau's object then it's just an addition of the signal to the PHSx register. So you can modulate the phase directly from the samples like that:
     {{ Phase Modulation from a WAV file }}
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
      Freq   = 900_000                             'Carrier frequency
      OutPin = 11                                  'Pin that outputs moduladet carrier
      ModInt = 3                                   'Modulation Intensity 0..23
    
    PUB Main | x,p,time
      Synth(OutPin, Freq)                          'set NCO out with Freq
      dira[OutPin] := 1                            'enable output on Pin
      
      x := clkfreq / 11_025
      time := cnt
      
      repeat
        p := @wav1 + 44
        repeat while p++ < @wav1_end    
           phsa += byte[p] << ModInt               'phase modulate Freq output
           waitcnt(time += x)
    
    DAT
    wav1      file  "be_back.wav"
    wav1_end  byte  0
    
    PUB Synth(Pin_, Freq_) | s, d
        Freq_ := Freq_ #> 0 <# 128_000_000        'limit frequency range
        if Freq_ < 500_000                        'if 0 to 499_999 Hz,
           CTRA := constant(%00100 << 26)         '..set NCO mode
           s := 1                                 '..shift = 1
        else                                      'if 500_000 to 128_000_000 Hz,
           CTRA := constant(%00010 << 26)         '..set PLL mode
           d := >|((Freq_ - 1) / 1_000_000)       'determine PLLDIV
           s := 4 - d                             'determine shift
           CTRA |= d << 23                        'set PLLDIV
        FRQA := fraction(Freq_, CLKFREQ, s)       'Compute FRQx value
        CTRA |= Pin_                              'set PINA to complete CTRx value
    
    PRI fraction(a, b, shift) : f
        if shift > 0                              'if shift, pre-shift a or b left
           a <<= shift                            'to maintain significant bits while 
        if shift < 0                              'insuring proper result
           b <<= -shift
     
        repeat 32                                 'perform long division of a/b
          f <<= 1
          if a => b
             a -= b
             f++           
          a <<= 1  
    
    I don't have a receiver for the modulated carrier, so I can't really test it. There may well be some little mistake somewhere in the posted code.

    Andy
  • Ariba wrote:
    The DUTY output of a counter is somewhat similar to a bitstream generated by the SigmaDelta ADC, so if you put this DUTY output from the sample player to the Pin on which the Modulaterobject expects the ADC input, it should work without any resistors and capacitors.
    You do make a convincing argument! But, more to the point, your later statement, "But it makes not much sense to go over a DAC -> ADC on a Pin just to use a premade object," makes even more sense.

    -Phil
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2017-10-10 02:59
    Just looked at the schematic again. You should be transmitting the DUTY mode output to P8, not P9. P9 is the output pin for the ADC, and any outputs there will be ORed with the ADC feedback.

    -Phil
  • mstrammstram Posts: 49
    edited 2017-10-10 09:03
    @Andy
    >I don't have a receiver for the modulated carrier, so I can't really test it.

    I'm just using a cheap am/fm "clock" radio (prob ~30 years old), doncha have one of those ?

    >But it makes not much sense to go over a DAC -> ADC on a Pin just to use a premade object. If you look how the Phase is modulated in Beau's object then it's just an addition of the signal to the PHSx register. So you can modulate the phase directly from the samples like that

    This was part of a "greater plan" ;)

    I've been trying to find or write a "generic" radio transmitter object than I can "hook" into any of the audio objects in the Obex or prop library.

    I.e. the Sidcog, SneCog, morse etc.

    So far the following code works (kinda) with SneCog but only with one "channel" (left or right) at a time.)

    With SidCog I just hear noise though.

    It is from Pedward's demo-direct-2m-fm-broadcast-modulation-with-the-propeller" code

    That code btw is so far the "gold standard" for playing a wav file over the radio !

    With NO TRANSMITTING antenna, my cheap clock radio gets an almost crystal clear / no static signal from anywhere in my tiny condo !

    I guess?? the wav file is MUCH "cleaner" than the SneCog / Sidcog ??, or is it more likely an incompatibilty with the way I'm trying to use the counter's PLL mode ?

    Instead of playing a wav file like this :
    Con
     _clkmode = xtal1 + pll16x
        _xinfreq = 5_000_000    
     SAMPRATE = 11_025
    
    PUB FmTransmit |p,x,time
    
      CTRA := %00010_111 << 23 | txpin '+ 0  'PLL SingleEnded
    
      x := clkfreq / SampRate
    
     repeat
        p := @wav1 '+ 44
        time := cnt
    
        repeat while p++ < @wav1_end   ' just continue from one 'File to next
          FRQA := magicnum + byte[p] << Vol ' 10 '10 seems best
          waitcnt(time += x)
    
    DAT                                                      
    wav1 byte
    'File "be_back.wav"
    wav1_end byte 0
    
    
    

    I'm transmitting the SneCog with this :
    ..... as above code block till repeat 
     
     repeat
        p := INA[rightPin]   ' or leftpin
        time := cnt
          FRQA := magicnum + byte[p] << Vol ' 10 '10 seems best
          waitcnt(time += x)
    


    Beau's Adc object was just another code example I thought might be doing something differently than other objects I have looked at.

    I have read the prop manual, and the AN001-P8X32ACounters-v2.0.pdf, and have searched / read every example I can find on how to do modulation with the counters.

Sign In or Register to comment.