TAQOZ - ADC using Smart Pin - run in new cog

twm47099twm47099 Posts: 866
edited 2019-01-22 - 02:53:02 in Propeller 2
I had previously been able (with a lot of help) to use a Smart Pin as an ADC to read a voltage from a potentiometer. The program is at this link:
forums.parallax.com/discussion/comment/1461499/#Comment_1461499
I have tried to do the same with TAQOZ. My code is:
---  ------------------------------------------------------
---	**** adcsp.fth
---	UsePin 22 as smart pin in ADC mode
---  ------------------------------------------------------
---	Define Constants
--- ADC_MODE from spin2 program that worked

  %0000_0000_000_100011_0000000_00_01111_0 := ADC_MODE 
   22 := ADC_PIN 
   4096 := ADC_CYCLES

: adcsp  (  --   )
ADC_PIN  PIN  F 		' set pin dir = 0
ADC_MODE WRPIN 
ADC_CYCLES WXPIN 
0 WYPIN
L			' set pin dir = 1
cnt@ ADC_CYCLES + WAITCNT 	' wait ADC_CYCLES
RDPIN . CRLF @PIN . CRLF ;

It doesn't work. I get 0 for RDPIN regardless of the voltage setting.
I think that I don't have to put ADC_PIN on the stack for WRPIN, WXPIN, and WYPIN since I used the PIN word to select the pin to use as a smart pin. However, I have tried a version with ADC_PIN before each of those lines. That also didn't work. I'm also not sure if waitcnt is the best way to stall the program while the smart pin collects the bits.

Help will be greatly appreciated.
Tom

Comments

  • I found one error. I was getting the "???" error when the binary number was entered. I can't have underscores in the binary number.

    But now when I try to run the program I get a mess:
    TAQOZ# adcsp
    .SDSS16G 3665_3133 NO NAME    32k 15,189M
      0: PFTH103      $0000_4040   2016.11.24.17.36   .          .....   0
      1: Bh - c o. l  $1C00_3F80   1980.03.24.00.03   PFTH103    .....   4,294,901,760
      3: THINKI~1.PDF $0000_65C0   2014.02.24.21.27   %PDF-1.3.%.....2   4,499,830
      4: Bd o c  .    $FFC0_3F80   2107.15.24.31.63   PFTH103    .....   4,294,967,295
      6: ANDSOF~1.DOC $0000_6200   2014.01.24.14.37   ................   476,160
      7: B  I n f. o  $1D00_3F80   1980.03.24.00.03   PFTH103    .....   110
      9: SYSTEM~1     $0000_8840   2017.07.24.20.22   .          ..k..   0
     10: 3204GOOD.FTH $0000_8880   2019.01.24.19.21   --  ------------   1,341
     14: EXTEND  .FTH $0000_88C0   2019.01.24.19.21   TAQOZ..{..use th   3,069
     15: _BOOT_P2.BIX $0000_8900   2019.01.24.20.08   X...P2-ES   ....   131,072
    .SDSS16G 3665_3133 NO NAME    32k 15,189MÎÎ0ÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎÎ
    
    In this case (TAQOZ v 1.1) it just prints out the SD directory and a string of nonsense characters.

    Without the boot SD (TAQOZ v1.0) it shows the following which looks like an empty directory

    TAQOZ# adcsp
    ........ 0000_0000            0k 0M
     :|Z    . y  $0000_0000   2049.03.15.12.26   825,499,750
    
    ........ 0000_0000            0k 0M
     :|Z    . y  $0000_0000   2049.03.15.12.26   825,499,750
    2009
     ok
    TAQOZ#
    
    Note for these two prinouts I had changed the last line of ADCSP to:
    RDPIN . CRLF  ;
    
    The value RDPIN puts on the stack is 2009 (it doesn't change regardless of where the pot is set. However, it does change depending on the value of the constant ADC_CYCLES.
  • Peter JakackiPeter Jakacki Posts: 9,828
    edited 2019-01-20 - 08:37:54
    While the ' symbol is a comment in p2asm it is entirely different in TAQOZ. The ' symbol will compile the address of the following word after which it will still be compiling whatever you thought was part of a comment, but it isn't, such as "dir = 0" which is why it does a "DIR". Try using the \ or --- words for comments.

    BTW, the reason the binary number fails is simply because there are too many characters in the number that end up overflowing the word buffer but symbols are fine normally. The next version ROM increases this buffer size.
    TAQOZ# %1011_0011---1111 .l $0000_0B3F ok
    
  • Peter,
    Thanks for the help. I've got to make some cheat sheets for the different languages, so I stop making silly mistakes.
    Here's the code that works. It will continuously measure the voltage and print the raw value. Press the number 1 to stop.
    Next step will be to run it in a newcog. I think I need to use a variable to send the adc value between cogs. Is that correct?
    I want to try some of the other Smart Pin modes to add to this one and the ones in your Intro to TAQOZ document.

    Thanks again,
    Tom
    ---  ------------------------------------------------
    ---
    ---	**** adcsp.fth
    ---	Use Pin 22 as a Smart Pin in ADC mode
    ---  
    ---  ------------------------------------------------
    ---
    ---	Define Constants
    --- ADC_MODE from spin2 program 
    
      %00000000000100011000000000011110 := ADC_MODE 
       22 := ADC_PIN 
       16384 := ADC_CYCLES
    
    : adcsp  ( -- )
    ADC_PIN PIN F 	  \ set pin dir = 0
    ADC_MODE WRPIN 
    ADC_CYCLES WXPIN 
    0 WYPIN
    L 1 ms		  \ set pin dir = 1 to start and delay
    Begin		  \ measure continuously
     RDPIN CRLF . 
     100 ms
    KEY 1 and UNTIL	   \ press 1 to stop
    ;
    
  • twm47099twm47099 Posts: 866
    edited 2019-01-22 - 03:53:51
    Peter,
    I've been able to modify the above program to run in a new cog and print the data to the terminal in the original cog.
    The modifications are shown below.
    After both definitions adcsp and adcdata are loaded, I type:
    1 NEWCOG
    ' adcsp 1 TASK W!
    
    and then adcdata to run the program.

    I tried to put
    1 NEWCOG
    ' adcsp 1 TASK W!
    
    into the definition of adcdata, but that did not work. Is it possible to have to start a newcog and function in a definition and use a variable that can be accessed in any cog?
    ------------------------------------------------------
    ---	**** adcspnewcog.fth
    ---	UsePin 22 as smart pin in ADC mode
    --- 	adcsp runs in cog 1
    --- 	raw data is printed to terminal from cog 0
    ------------------------------------------------------
    ---	Define Constants
    --- ADC_MODE from spin2 program 
      %00000000000100011000000000011110 := ADC_MODE 
       22 := ADC_PIN 
       16384 := ADC_CYCLES
       2696 := CALMIN   13368 := CALMAX  3.30 := VREF 
    
       long vadcspraw         \ variable used to move data between cogs
    
    : adcsp  ( -- )
    ADC_PIN PIN F 	  \ set pin dir = 0
    ADC_MODE WRPIN  \ ADC_MODE
    ADC_CYCLES WXPIN 	\ ADC_CYCLES
    0 WYPIN
    L 1 ms		  \ set pin dir = 1 and delay
    Begin		  \ measure continuously
     RDPIN vadcspraw !
     10 ms
    AGAIN
    ;
    
    : adcdata
    BEGIN
      vadcspraw @ dup CRLF .
      CALMIN - VREF * 10 * CALMAX CALMIN - /
      CRLF .AS" #.### volts "
      100 ms
    KEY 1 and UNTIL	   \ press 1 to stop
    1 COGSTOP
    ;
    
    \ enter next 2 lines and then adcdata <ret>
     1 NEWCOG
    ' adcsp 1 TASK W! 
    \ --------------
    
    
  • I accidentally created VREF as 3.30, but the program works reporting the voltage as 3.3 volts with the pot at one extreme and 20 to 40 mV at the other -- both in agreement with a DVM reading.

    I recall reading in Starting Forth that putting a decimal in a number makes it a double precision number (or something like that), can you explain how this works in TAQOZ?
  • twm47099 wrote: »
    I accidentally created VREF as 3.30, but the program works reporting the voltage as 3.3 volts with the pot at one extreme and 20 to 40 mV at the other -- both in agreement with a DVM reading.

    I recall reading in Starting Forth that putting a decimal in a number makes it a double precision number (or something like that), can you explain how this works in TAQOZ?

    In some Forths they do this but TAQOZ just allows any symbol to be mixed in which also includes commas. Interestingly I was just thinking about which method I might use to enter double numbers but the decimal point is used as position indicator in 32-bit integers that can be read by software to determine scaling. The print routine automatically handles 64-bit numbers and using <D> before any print will cause it to grab the upper 32-bits to be handled internally after which this internal high word is reset to zero again.

    There are however very few double precision operators in TAQOZ, mainly the UM* and UM// and perhaps the */ that uses both of these operators but returns a 32-bit result. I just had a need for it when I wanted to calculate the counter value from the clock rate with:
    : NCOCNT ( hz -- cntval )	CLKHZ 4 << SWAP U/ 0 $10 ROT UM// DROP NIP ; 
    
    The double number is the 0 $10 where the $1.0000.0000 I suppose is scaled up by 4 bits for some extra precision. It would be nice to be able to enter this as a double number, especially for decimal numbers.
  • This modification uses 2 Smart Pins to measure and print the value of 2 voltage sources. I simply duplicated the original code and use the suffix 1 or 2 for the constant ADC_PIN and the global variable (vadcspraw).
    ---  
    
    ------------------------------------------------------
    ---	**** adcspnewcog2ch.fth
    ---     Read 2 voltage sources (2 channel ADC) 
    ---	Use Pins 22 & 23 as smart pins in ADC mode
    --- 	adcsp runs in cog 1
    --- 	raw data is printed to terminal from cog 0
    ------------------------------------------------------
    ---	Define Constants
    --- ADC_MODE from spin2 program 
    
      %00000000000100011000000000011110 := ADC_MODE 
       22 := ADC_PIN1
       23 := ADC_PIN2 
       16384 := ADC_CYCLES
       2696 := CALMIN   13368 := CALMAX  3.30 := VREF 
    
       long vadcspraw1
       long vadcspraw2
    
    : adcsp  ( -- )  \ this will be run in cog 1
    
    --- Setup Smart Pin P22 for Channel 1
    ADC_PIN1 PIN F 	  \ set pin dir = 0
    ADC_MODE WRPIN  \ ADC_MODE
    ADC_CYCLES WXPIN 	\ ADC_CYCLES
    0 WYPIN
    
    --- Setup Smart Pin P23 for Channel 2
    ADC_PIN2 PIN F 	  \ set pin dir = 0
    ADC_MODE WRPIN  \ ADC_MODE
    ADC_CYCLES WXPIN 	\ ADC_CYCLES
    0 WYPIN
    
    --- Start both channels
    ADC_PIN1 PIN L        \ set pin22 dir = 1
    ADC_PIN2 PIN L 1 ms   \ set pin23 dir = 1 and delay
    
    --- Read Smart Pins store result in global variables
    Begin		  \ measure continuously
     ADC_PIN1 PIN  RDPIN vadcspraw1 !
     ADC_PIN2 PIN  RDPIN vadcspraw2 !
     10 ms
    AGAIN
    ;
    
    : adcdata ( -- )   \ prints ADC data from adcsp
    BEGIN
      CRLF ." Ch #1 "
      vadcspraw1 @ dup  .
      CALMIN - VREF * 10 * CALMAX CALMIN - /
      CRLF .AS" #.### volts "
    
      CRLF ." Ch #2 "
      vadcspraw2 @ dup  .
      CALMIN - VREF * 10 * CALMAX CALMIN - /
      CRLF .AS" #.### volts " CRLF
      200 ms
    KEY 1 and UNTIL	   \ press 1 to stop
    1 COGSTOP
    ;
    
    \ enter next 2 lines and then adcdata <ret>
     1 NEWCOG
    ' adcsp 1 TASK W! 
    \ --------------
    
    
  • I modified the code from twm47099 to get a so called talkthrough example.
    Meaning reading the ADC port and output it again to DAC port.
    (The "hello world" of the DSP guys.)
    Unfortunately the speed was quite slow. In
    the osci screenshot you may see the yellow input at 300 Hz and below the output.
    At 1 khz I got nearly a rectangle signal.

    Below my source code. I was using only one input and one output.
    What did I wrong? Or is this already the upper limit of the Prop2 with Taqoz?
    Same effect even with no terminal output, running only one cog for signal processing.

    Regards
    Markus
    ---  
    
    ------------------------------------------------------
    ---	**** adcspnewcog2ch.fth
    ---     Read 2 voltage sources (2 channel ADC) 
    ---	Use Pins 5 & 13 as smart pins in ADC mode
    --- 	adcsp runs in cog 1
    --- 	raw data is printed to terminal from cog 0
    --- 	expanden to a talkthrough module
    --- 	the ADC results are sent imediately to a DAC
    ------------------------------------------------------
    ---	Define Constants
    --- ADC_MODE from spin2 program 
    
      %00000000000100011000000000011110 := ADC_MODE 
       5 := ADC_PIN1
       13 := ADC_PIN2 
       6 := DAC_PIN1
       14 := DAC_PIN2
       16384 := ADC_CYCLES  
       2696 := CALMIN   13368 := CALMAX  3.30 := VREF 
    
       long vadcspraw1
       long vadcspraw2
    
    : adcsp  ( -- )  \ this will be run in cog 1
    
    --- Setup Smart Pin P5 for Channel 1
    ADC_PIN1 PIN F 	  \ set pin dir = 0
    ADC_MODE WRPIN  \ ADC_MODE
    ADC_CYCLES WXPIN 	\ ADC_CYCLES
    0 WYPIN
    
    --- Setup Smart Pin P13 for Channel 2
    ADC_PIN2 PIN F 	  \ set pin dir = 0
    ADC_MODE WRPIN  \ ADC_MODE
    ADC_CYCLES WXPIN 	\ ADC_CYCLES
    0 WYPIN
    
    --- Start both ADC channels
    ADC_PIN1 PIN L        \ set pin5 dir = 1
    ADC_PIN2 PIN L 1 ms   \ set pin23 dir = 1 and delay
    
    --- Start both DAC channels
    DAC_PIN1 PIN DAC
    DAC_PIN2 PIN DAC
    
    --- Read Smart Pins store result in global variables
    Begin		  
     ADC_PIN1 PIN  RDPIN dup vadcspraw1 ! 
     DAC_PIN1 PIN WYPIN 
    AGAIN
    ;
    
    : adcdata ( -- )   \ prints ADC data from adcsp
    BEGIN
      CRLF ." Ch #1 "
      vadcspraw1 @ dup  .
      CALMIN - VREF * 10 * CALMAX CALMIN - /
      CRLF .AS" #.### volts "
    
      CRLF ." Ch #2 "
      vadcspraw2 @ dup  .
      CALMIN - VREF * 10 * CALMAX CALMIN - /
      CRLF .AS" #.### volts " CRLF
      500 ms
    KEY 1 and UNTIL	   \ press 1 to stop
    1 COGSTOP
    ;
    
    \ enter next 2 lines and then adcdata <ret>
    1 NEWCOG
    ' adcsp 1 TASK W! 
    \ --------------
    
    
    800 x 480 - 24K

  • Markus,
    That was an early version.
    The link below & following posts give some better info. One thing is the value in ADC_CLYCLES. That is the number of cycles to get a reading, The higher the number, the longer the ADC measurement takes. There is a post (somewhere) which correlates the number of cycles with the number of bits per ADC value. I believe I was looking at 12 bit ADC data. I wasn't looking for speed.

    Also the calibration constants were made empirically for my set up. the better way is to get the ADC values for ground and Vio and set them into CALMIN and CALMAX.

    forums.parallax.com/discussion/comment/1461428/#Comment_1461428

    hope this helps
    Tom
  • The post that correlates the value of ADC_CYCLES (wxpin) with bits is here:

    https://forums.parallax.com/discussion/169602/characterizing-p2-eval-analog-performance

    See the chart P2-EVAL-ENOB.jpg
    That was for the A version of the P2. I don't know if there should be any difference with the new chips.
    Tom
  • Tom,

    many thanks for the hints.
    Its really hard actually to find the right info, specially regarding the quite
    complex smartpin story.
    I should suggest the name "COMPLEXPIN" instead ;-)
    I will try to do more research in the next days, hoping to get at least a 10 kHz talkthrough example.

    Markus


  • I've been meaning to revisit A/D modes since the improved RevB and C silicon. I will try to do this in the next few days :)
  • Peter,

    finally I found out with my talkthrough experiments, that the DAC command is extreme slow, or better said is using a very slow DAC mode.
    I found some assembler code in your dropbox (see below), which was promising 300 k*samples and more, and tried to translate it into
    Taqoz. Unfortunately this code is using an interrupt, and as far as I have seen
    Taqoz isn't supporting any interrupts (?, maybe I am wrong).

    Maybe words like DAC8FLASH, DAC8 , DAC16 and DAC12 would be nice.
    So as less resolution as faster.
    And maybe some similar for the ADC conversion, like ADC8, ADC12, ADC16 or so.

    Thanks

    Markus

    ' 12-bit analog to digital to analog, 19.5k samples/second
    
    dat	org
    
    	wrpin	##%101<<18+%01_00011_0,#5	'12-bit pwm dithered dac
    	wxpin	##4096,#5			'4,096 clocks per sample
    	dirh	#5				'enable dac
    
    	wrpin	##%100011<<15,#4		'adc on
    
    	wrpin	##%0001<<28+%01100_0,#3		'count adc highs
    	wxpin	##4096,#3			'4,096 clocks per sample
    	dirh	#3				'enable counter
    
    	setse1	#%01<<6+3			'se1 triggers on adc sample
    
    loop	waitse1					'wait adc sample
    
    	rdpin	x,#3				'get adc sample
    	shl	x,#4				'shift it up
    	wypin	x,#5				'set dac
    	jmp	#loop				'loop
    
    	x	res	1			'sample buffer
    
    
  • MJBMJB Posts: 1,198
    MGreim wrote: »
    Peter,

    finally I found out with my talkthrough experiments, that the DAC command is extreme slow, or better said is using a very slow DAC mode.
    I found some assembler code in your dropbox (see below), which was promising 300 k*samples and more, and tried to translate it into
    Taqoz. Unfortunately this code is using an interrupt, and as far as I have seen
    Taqoz isn't supporting any interrupts (?, maybe I am wrong).

    Maybe words like DAC8FLASH, DAC8 , DAC16 and DAC12 would be nice.
    So as less resolution as faster.
    And maybe some similar for the ADC conversion, like ADC8, ADC12, ADC16 or so.

    Thanks

    Markus

    ' 12-bit analog to digital to analog, 19.5k samples/second
    
    dat	org
    
    	wrpin	##%101<<18+%01_00011_0,#5	'12-bit pwm dithered dac
    	wxpin	##4096,#5			'4,096 clocks per sample
    	dirh	#5				'enable dac
    
    	wrpin	##%100011<<15,#4		'adc on
    
    	wrpin	##%0001<<28+%01100_0,#3		'count adc highs
    	wxpin	##4096,#3			'4,096 clocks per sample
    	dirh	#3				'enable counter
    
    	setse1	#%01<<6+3			'se1 triggers on adc sample
    
    loop	waitse1					'wait adc sample
    
    	rdpin	x,#3				'get adc sample
    	shl	x,#4				'shift it up
    	wypin	x,#5				'set dac
    	jmp	#loop				'loop
    
    	x	res	1			'sample buffer
    
    

    just thinking ...

    could you use the streamer to get the ADC data into HUB and the streamer of another COG to get them to DAC ?
    sure in one COG you will only have one streamer available
    and you would have to sync them somehow

    but it would not cost you a full COG for the LOOP
  • MGreim wrote: »
    Tom,

    many thanks for the hints.
    Its really hard actually to find the right info, specially regarding the quite
    complex smartpin story.
    I should suggest the name "COMPLEXPIN" instead ;-)
    I will try to do more research in the next days, hoping to get at least a 10 kHz talkthrough example.

    Markus


    It's called smart pin because you have to be smart to use it. :-)
  • It's called smart pin because you have to be smart to use it. :-)

    you have got it :-)))
Sign In or Register to comment.