Shop OBEX P1 Docs P2 Docs Learn Events
MCP3301 ADC(single channel, 13 bit); no obex object. — Parallax Forums

MCP3301 ADC(single channel, 13 bit); no obex object.

Clock LoopClock Loop Posts: 2,069
edited 2010-02-08 04:06 in Propeller 1
I downloaded and tried the 3201 object, but something is wrong and I am not sure what.
I don't have experience with comms to an ADC so i figured I would ask here if anyone has already done this chip.
I also don't yet have a scope that can help me in that task.

Anyone have a 3301 working with the prop?

Comments

  • BradCBradC Posts: 2,601
    edited 2010-02-07 08:59
    Yeah, I have a couple working here. I'm sorry this code is a mess but I just pulled it out of the last working copy of the stuff I was playing with a while back. It works though.

    I was dong audio stuff with it at about 19.5k so there are a stack of waitcnt in there to slow the sampling down. You don't have to run it that slow.
    Ignore the rest of the code, it's doing all sorts of stupid things.

    atod
                  org       0
    
                  mov       adc_c, cnt
                  add       adc_c, adc_cycles
                  mov       adc_fpos, par
                  add       adc_fpos, #4
                  mov       dira, adc_dirval
                  mov       outa, #4                ' CS High, CLK Low
                  mov       adc_lta, #0
                  mov       adc_sta, #0
                  mov       adc_lfopos, par
                  add       adc_lfopos, #32
    
                  mov       adc_filtered, #0
                  mov       adc_divide, #4
    :toploop
                  or        outa, adc_dbg
                  neg       adc_sample,adc_filtered
                  wrlong    adc_sample, par
                  wrlong    adc_frame, adc_fpos
                  wrlong    adc_lfo, adc_lfopos
                  add       adc_lfo, adc_lfoincr
    
    
    :loop
    
                  waitcnt   adc_c, adc_cycles
    
    {-- this bit samples the ADC --}
                  andn      outa, #4                ' CS Low
                  mov       adc_bl, cnt
                  add       adc_bl, adc_acq
                  waitcnt   adc_bl, adc_acq
                  or        outa, #1                ' Clk High
                  waitcnt   adc_bl, adc_acq
                  andn      outa, #1                ' CS Low
                  waitcnt   adc_bl, adc_acq
                  or        outa, #1                ' Clk High
                  waitcnt   adc_bl, adc_clk
    
                  mov       adc_sample, #0
                  mov       adc_r1, #14
    :bitloop
                  andn      outa, #1                ' Clk Low
                  waitcnt   adc_bl, adc_clk
                  test      adc_in, ina wz
                  shl       adc_sample, #1
                  muxnz     adc_sample, #1
                  or        outa, #1                ' Clk High
                  waitcnt   adc_bl, adc_clk
                  djnz      adc_r1, #:bitloop
    
    {-- END ADC SAMPLE --}
    
                  andn      outa, adc_dbg
                  and       adc_sample, adc_mask
                  shl       adc_sample, #19
                  sar       adc_sample, #20
    
                  or        outa, #4
                  andn      outa, #1
    
                  mov       adc_r1, adc_sample
                  subs      adc_r1, adc_filtered
                  sar       adc_r1, #2
                  adds      adc_filtered, adc_r1
    
                  djnz      adc_divide, #:loop
                  mov       adc_divide, #4
                  add       adc_frame, #1
                  jmp       #:toploop
    
    adc_bias      long      $8000_0000
    adc_acq       long      40
    adc_clk       long      25
    adc_dirval    long      %0101 + 1<<21
    adc_cycles    long      1023
    adc_filtered  long       1
    adc_in        long      1<<1
    adc_frame     long      -60000
    adc_mask      long      $1FFF
    adc_lfoincr   long      $6FFF
    adc_dbg       long      1<<21
    
    adc_fpos      res       1                       ' Pointer to HUB Frame variable
    adc_c         res       1                       ' Overall loop timer
    adc_bl        res       1
    adc_sample    res       1
    adc_old       res       1
    adc_new       res       1
    adc_lfo       res       1
    adc_lfopos    res       1
    
    adc_2sample   res       1
    adc_2old      res       1
    adc_2new      res       1
    
    adc_temp      res       1
    adc_sta       res       1
    adc_lta       res       1
    adc_divide    res       1
    adc_r1        res       1
    adc_r2        res       1
    adc_noisegate res       1
    adc_noiseflag res       1
    adc_lastsamp  res       1
    
                  fit       $1f0
    
    

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Life may be "too short", but it's the longest thing we ever do.
  • Clock LoopClock Loop Posts: 2,069
    edited 2010-02-07 09:55
    I know nothing about prop asm, but by the looks of what you show in your code, I could use this basic adc and your code to learn both prop asm, and this adc.
    If you could dumb it down, add comment lines, it would be a great help for me.
  • BradCBradC Posts: 2,601
    edited 2010-02-07 10:19
    Clock Loop said...
    I know nothing about prop asm, but by the looks of what you show in your code, I could use this basic adc and your code to learn both prop asm, and this adc.
    If you could dumb it down, add comment lines, it would be a great help for me.

    Yeah, I'll try and clean it up and re-post it tomorrow for you. The code is dirty and ugly as I was trying all sorts of hacky stuff to get a clean audio signal.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    Life may be "too short", but it's the longest thing we ever do.
  • Clock LoopClock Loop Posts: 2,069
    edited 2010-02-08 04:06
    Im attempting to learn asm using what you have written in combination with the prop manual.
    Heres what i have so far, many redundant lines right now, till i change them into what they really are.

    DAT
    
    '  ASSEMBLY
    
                  org       0                         'reset assembly pointer, this is register 0
    
    atod      'asm address name 
                  
                  mov       adc_c, cnt                'Current 32-bit System Counter value written to adc_c     4 clocks      
                  add       adc_c, adc_cycles         'add adc cycles to system count.  4 clocks
    
                  mov       adc_fpos, par             'MOV  Destination, <#>Value   'Set register to a value.    4 clocks      Par = Cog Boot Parameter register.                                                       
                  add       adc_fpos, #4              'ADD  Value1, <#>Value2       'Add unsigned values.  4 clocks 
    
                  mov       dira, adc_dirval          'MOV  Destination, <#>Value   'Set register to a value.    4 clocks        
                  mov       outa, #4                  'MOV  Destination, <#>Value   'Set register to a value.    4 clocks                                   'CS High, CLK Low     
    
                  mov       adc_lta, #0               'MOV  Destination, <#>Value   'Set register to a value.    4 clocks        
    
                  mov       adc_sta, #0               'MOV  Destination, <#>Value   'Set register to a value.    4 clocks        
    
                  mov       adc_lfopos, par           'MOV  Destination, <#>Value   'Set register to a value.    4 clocks      Par = Cog Boot Parameter register.
                  add       adc_lfopos, #32           'ADD  Value1, <#>Value2       'Add unsigned values.  4 clocks  
    
                  mov       adc_filtered, #0          'MOV  Destination, <#>Value   'Set register to a value.    4 clocks  
    
                  mov       adc_divide, #4            'MOV  Destination, <#>Value   'Set register to a value.    4 clocks  
    
    :toploop   'asm address name      
                  or        outa, adc_dbg             'OR  Value1, <#>Value2       'Bitwise OR values.       4 clocks
    
                  neg       adc_sample, adc_filtered   'NEG  NValue, <#>SValue      'Get negative of a number.     4 clocks
                  wrlong    adc_sample, par           'WRLONG  Value, <#>Address   'Write long to main memory.    7 to 22 clocks
    
                  wrlong    adc_frame, adc_fpos       'WRLONG  Value, <#>Address   'Write long to main memory.    7 to 22 clocks      
    
                  wrlong    adc_lfo, adc_lfopos       'WRLONG  Value, <#>Address   'Write long to main memory.    7 to 22 clocks      
                  add       adc_lfo, adc_lfoincr      'ADD  Value1, <#>Value2       'Add unsigned values.  4 clocks   
    
    
    :loop  'asm address name
                 
                  waitcnt   adc_c, adc_cycles         'WAITCNT  Target,  <#>Delta   'Pause execution temporarily.  5 clocks + 
    
    {-- this bit samples the ADC --}
                  andn      outa, #4                  'ANDN  Value1, <#>Value2     'Bitwise AND value with NOT of another.  4 clocks                       ' CS Low
    
                  mov       adc_bl, cnt               'MOV  Destination, <#>Value   'Set register to a value.    4 clocks  
                  add       adc_bl, adc_acq           'ADD  Value1, <#>Value2       'Add unsigned values.  4 clocks   
                  waitcnt   adc_bl, adc_acq           'WAITCNT  Target, <#>Delta   'Pause execution temporarily.  5 clocks +   
    
                  or        outa, #1                  'OR  Value1, <#>Value2       'Bitwise OR values.       4 clocks                                      ' Clk High
    
                  waitcnt   adc_bl, adc_acq           'WAITCNT  Target, <#>Delta   'Pause execution temporarily.  5 clocks + 
    
                  andn      outa, #1                  'ANDN  Value1, <#>Value2     'Bitwise AND value with NOT of another.  4 clocks                       ' CS Low
    
                  waitcnt   adc_bl, adc_acq           'WAITCNT  Target, <#>Delta   'Pause execution temporarily.  5 clocks + 
    
                  or        outa, #1                  'OR  Value1, <#>Value2       'Bitwise OR values.       4 clocks                                      ' Clk High
    
                  waitcnt   adc_bl, adc_clk           'WAITCNT  Target, <#>Delta   'Pause execution temporarily.  5 clocks + 
    
                  mov       adc_sample, #0            'MOV  Destination, <#>Value   'Set register to a value.    4 clocks     
    
                  mov       adc_r1, #14               'MOV  Destination, <#>Value   'Set register to a value.    4 clocks     
    
    :bitloop  'asm address name  
    
                  andn      outa, #1                  'ANDN  Value1, <#>Value2     'Bitwise AND value with NOT of another.  4 clocks                        ' Clk Low
    
                  waitcnt   adc_bl, adc_clk           'WAITCNT  Target, <#>Delta   'Pause execution temporarily.            5 clocks + 
    
                  test      adc_in, ina wz            'TEST  Value1, <#>Value2     'Bitwise AND values to affect flags only.   4 clocks
    
                  shl       adc_sample, #1            'SHL  Value, <#>Bits         'Shift value left by specified number of bits.  4 clocks
                  muxnz     adc_sample, #1            'MUXNZ  Destination, <#>Mask 'Set discrete bits of value to state of !Z.
    
                  or        outa, #1                  'OR  Value1, <#>Value2       'Bitwise OR values.       4 clocks                                       ' Clk High
    
                  waitcnt   adc_bl, adc_clk           'WAITCNT  Target, <#>Delta   'Pause execution temporarily.            5 clocks +
    
                  djnz      adc_r1, #:bitloop         'DJNZ  Value,  <#>Address     'Decrement value and jump to address if not zero.  4 or 8 clocks
    
    {-- END ADC SAMPLE --}
    
                  andn      outa, adc_dbg
    
                  and       adc_sample, adc_mask
                  shl       adc_sample, #19
                  sar       adc_sample, #20
    
                  or        outa, #4
                  andn      outa, #1
    
                  mov       adc_r1, adc_sample
                  subs      adc_r1, adc_filtered
                  sar       adc_r1, #2
                  adds      adc_filtered, adc_r1
    
                  djnz      adc_divide, #:loop
                  mov       adc_divide, #4
    
                  add       adc_frame, #1
    
                  jmp       #:toploop
    
    
    
    
    
    adc_bias      long      $8000_0000
    adc_acq       long      40
    adc_clk       long      25
    adc_dirval    long      %0101 + 1<<21
    adc_cycles    long      1023                        'this would be 
    adc_filtered  long       1
    adc_in        long      1<<1
    adc_frame     long      -60000
    adc_mask      long      $1FFF
    adc_lfoincr   long      $6FFF
    adc_dbg       long      1<<21
    
    adc_fpos      res       1                       '<Symbol>  RES  <Count>    Reserve next long(s)of Cog RAM for symbol.          ' Pointer to HUB Frame variable
    adc_c         res       1                                                                                                       ' Overall loop timer
    adc_bl        res       1
    adc_sample    res       1
    adc_old       res       1
    adc_new       res       1
    adc_lfo       res       1
    adc_lfopos    res       1
    
    adc_2sample   res       1
    adc_2old      res       1
    adc_2new      res       1
    
    adc_temp      res       1
    adc_sta       res       1
    adc_lta       res       1
    adc_divide    res       1
    adc_r1        res       1
    adc_r2        res       1
    adc_noisegate res       1
    adc_noiseflag res       1
    adc_lastsamp  res       1
    
                  fit       $1f0        'FIT <Address>  Validate previous instr/data fit below an address. 
    
    
    
Sign In or Register to comment.