Shop OBEX P1 Docs P2 Docs Learn Events
Microphone 2 serial / DAT to PUB — Parallax Forums

Microphone 2 serial / DAT to PUB

TurboManTurboMan Posts: 19
edited 2010-10-04 14:41 in Propeller 1
Sorry if this question is too simple. I'm new to the prop and have done a lot in BS2 and a little in SX assy. More hardware background then software.
With that said, here is my simple task. I have so many iterations of code I can't even pick one to put out here. I was using the microphone_to_headphone code and the FullDuplexSerialPlus code to simply pass microphone (78k sample) data out a serial port at 115200. At this point I just need to stream it out continually. I can decrease the sample rate but I need the baud rate. I've tried it a couple ways, each in their own cog and also tried a master cog grabbing data from microphone and then passing it off to the Serial port. I get data out but it's doesnt change. Probably my biggest confusion is the best way to get the microphone data from the assembly (DAT) out to the spin code. Can anyone simply tell me how to get the microphone data (from what I can understand it is the asm_sample that gets mov to frqb) into the FDSP code?

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2010-09-10 06:57
    First things first. A Baud of 115200 is a byte rate of 11520 bytes per second or a word rate of 5760 words per second (16-bit words). Those are your sample rates (unless you want to buffer up a short piece of sound, then send it at a slower rate).

    Given these limitations, what do you want to do?
  • TurboManTurboMan Posts: 19
    edited 2010-09-10 09:26
    Thanks Mike,
    You are correct.. fat finger 7.8K I tried the standard bit setting of "13" which was 9.77khz and thought maybe it was too fast with overhead and then tried to fool the loop into grabing every 10th scan and sending it out(7.8k which was my roughly my scan target. 9.77k would be even better if it would work.) I know I can probably change the PLL setting of the clk but won't that change the operation of the whole Prop as opposed to a single cog? Anyway to get back to your question, in a nut shell... this is not for music only for basic audio. I would like to scan an 8 bit sample (I know low quality), grab it and send it out the serial port. I can't use hardware controls since the device I'm sending it to isn't using HW. I figured I would need to use a start stop bit. This process would be continual. The device at the other end will ignore the data until it gets an activation bit from another device and would then grab a 10 or 20 sec capture of audio and then go about it's business. I probably could do this with something else but thought it would be an opportunity to use the prop and I like the ability to expand other ideas into the project as I go along (other cogs just waiting to be used).
  • Mike GreenMike Green Posts: 23,101
    edited 2010-09-10 10:19
    OK. Let's say you set up your ADC routine to provide 8-bit samples. Your maximum sample rate is about 330KHz. At 115200 Baud, your maximum transmit rate is 11520 bytes per second. What you need is a routine running in a cog that will grab a sample from the ADC routine and copy it to FullDuplexSerial's transmit buffer (using .tx()) on a regular basis that's less than the maximum transmit rate. You'd use WAITCNT to set the time tick. The ADC routine will be free-running leaving its value in a shared memory location (it should be simple to modify the microphone-to-headphone routine to do this).
  • TurboManTurboMan Posts: 19
    edited 2010-09-10 11:10
    That is what I originally tried to do. I looked at the HelloFullDuplexSerial.spin prog and modify it to grab data from the microphone code and send it to the serial code. Seemed simple but I went down in flames repeatedly!! I was able to put a fixed number in place of the data I was trying to capture and it would send it out the serial port fine but when I tried to capture the dynamic data from the adc, it would send out the same number stream. My thought was that even if I was out of sync, the data would at least be changing and it's not. this leaves me thinking that I'm just grabbing a static memory location that is not getting updated. I find a lot of examples of how to move data from cog to cog using only spin code but wasn't getting a good picture of how to get it out of assembly code to spin (or should I say to Main memory to be read using spin)... I guess that's my real road block.
  • TurboManTurboMan Posts: 19
    edited 2010-09-24 08:04
    Mike,
    I hate to keep beating this dead horse but I still am having problems grabing data from another Cog. It sounds simple but I can't seem to get it. I can send data from one to another. In the microphone code the PUB line is as follows.

    PUB StartAud (AudioSam)
    cognew(@asm_entry, 0)

    The Manual says that (AudioSam) would be a treated like a global variable ( thought that this would be a HUB Mem location). I'm trying to modify the HelloFullDuplexSerial prog to grab data from microphone and send it to FullDuplexSerialPlus. I can manually assign AudioSam to a bin num and it goes through to the terminal fine but I can't seem to grab it from Mic. How do I setup the Method to GET the data. Here is one of many attempts to GET the data????

    CON

    _clkmode = xtal1 + pll16x
    _xinfreq = 5_000_000


    OBJ
    Audio: "microphone_gg"
    SendSer: "FullDuplexSerialPlusGG"


    PUB XferAudio2Ser | AudioSam, AudioOut


    SendSer.start(31, 30, 0, 115200)
    audio.startaud (@AudioSam)
    repeat


    SendSer.bin(AudioSam, 31)
    SendSer.tx(13)
  • Mike GreenMike Green Posts: 23,101
    edited 2010-09-24 08:18
    You really need to post your whole program including the objects that you've modified. Use the "paperclip" icon attach the files to a reply.

    There are all sorts of examples of passing parameters from part of a program written in Spin to another part of the program written in assembly in its own cog. The "Getting Started and Key Thread Index" sticky thread here is a good starting place. Look at the assembly code examples and the machine language tutorial.
  • TurboManTurboMan Posts: 19
    edited 2010-09-24 08:42
    Thanks. I'll look at the link and I'll post after that if I still can't figure it out.

    Thanks again for responding
  • AribaAriba Posts: 2,690
    edited 2010-09-25 10:15
    Here is the MIC_to_headphones modified to send the samples with FullDuplexSerial:
    {{ MIC to Serial }}
    
    CON
    
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    
    ' At 80MHz the ADC/DAC sample resolutions and rates are as follows:
    '
    ' sample   sample               
    ' bits       rate               
    ' ----------------              
    ' 5       2.5 MHz               
    ' 6      1.25 MHz               
    ' 7       625 KHz               
    ' 8       313 KHz               
    ' 9       156 KHz               
    ' 10       78 KHz               
    ' 11       39 KHz               
    ' 12     19.5 KHz               
    ' 13     9.77 KHz               
    ' 14     4.88 KHz               
                                    
      bits   = 11
      micpin = 9
      fb_pin = 8
    
    OBJ
      ser : "FullDuplexSerial"
    
    VAR
      long smpl
       
    PUB go  | time
    
      ser.start(31,30,0,115_200)
      cognew(@asm_entry, @smpl)     'launch assembly program into a COG
    
      time := cnt
      repeat
        ser.tx(smpl)                'send smpl
        time += clkfreq/9_000       '9 kHz update rate
        waitcnt(time)
        
      
    DAT
    
    '
    '
    ' Assembly program
    '
                  org
    
    asm_entry     mov       dira,asm_dira                   'make pins 8 (ADC) output
    
                  movs      ctra,#micpin                    'POS W/FEEDBACK mode for CTRA
                  movd      ctra,#fb_pin
                  movi      ctra,#%01001_000
                  mov       frqa,#1
    
                  mov       asm_cnt,cnt                     'prepare for WAITCNT loop
                  add       asm_cnt,asm_cycles
    
                  
    :loop         waitcnt   asm_cnt,asm_cycles              'wait for next CNT value (timing is determinant after WAITCNT)
    
                  mov       asm_sample,phsa                 'capture PHSA and get difference
                  sub       asm_sample,asm_old
                  add       asm_old,asm_sample
                                                             
                  shr       asm_sample,#bits-8                'justify sample to 8 bits
    '              add       asm_sample,#48     'for test
    
                  wrlong    asm_sample,par                  'write to Spin variable smpl
        
                  jmp       #:loop                          'wait for next sample period
    '
    ' Data
    '
    asm_cycles    long      |< bits - 1                     'sample time
    asm_dira      long      |< fb_pin                       'output mask
    
    asm_cnt       res       1
    asm_old       res       1
    asm_sample    res       1
    
    You need to pass the address of a global variable in par to the cog, and then write the adc value to this variable with wrlong.

    Andy
  • TurboManTurboMan Posts: 19
    edited 2010-10-01 12:08
    Thanks Andy.
    Been putting out fires (I mean thermal incidents)lately and just getting back.
    This is great code. I have something close to this but yours is cleaner(i'm still learning). I originally was trying to have 3 seperate cogs, 1 data handler, 2 adc, 3 serial but I think I'm changing my method(no pun intended). I'll experiment more using your cleaner code.
    Thanks again!
  • TurboManTurboMan Posts: 19
    edited 2010-10-04 14:41
    Took me a few trys to figure out that you had switched mic and feedback pins around....the pin numbers were correct and I didn't pay close enough to the labels..
    Seems to work well and I will continue to add to this code.

    Thanks
Sign In or Register to comment.