Shop OBEX P1 Docs P2 Docs Learn Events
Counter Register Question - NCO (single ended) mode + pulse counter? — Parallax Forums

Counter Register Question - NCO (single ended) mode + pulse counter?

Dantes LegacyDantes Legacy Posts: 16
edited 2012-01-26 01:16 in Propeller 1
Hi guys,

I have a quick question that I hope you can help with. Basically I am trying to toggle any given pin as fast as possible WITHOUT assembly. The problem I am having is that I want to control the amount of times it toggles.

I am using a counter register to toggle a given pin as per the example shown in the AN001 apllication note in the 'Propeller Downloads' section. The code is shown below:
CON
  _clkmode = xtal1 + pll16x
  _xinfreq = 5_000_000

PUB Main
  NCO_single_ended_mode(13)

PUB NCO_single_ended_mode (PinNo)
''NOTES:
''FRQA values:
''  $8000_0000 = 12.6 MHz?
''  $0666_6666 = 2 MHz
''  $0000_0218 = 10 Hz
''  $0000_006B = 2 Hz
  ' mode PLL BPIN APIN
  dira[PinNo] := 1 'Set APIN to output
  ctra := %00100_000 << 23 + 1 << 9 + PinNo 'Establish mode and APIN (BPIN is ignored)
  frqa := $8000_0000 'Set FRQA so PHSA[31] toggles every clock
  repeat 'infinite loop, so counter continues to run

With this code, I can toggle the output of pin 13 (or any pin specified) to toggle VERY fast. Much faster than the '!OUTA[PinNo]' command does. As assembly is out of the question for this program, I want to see if it is possible to configure the second Counter Register (or Counter Register B) of this cog to somehow monitor the output of APIN from Counter Register A. For example, if you take an SPI clock pulse and use this program for it, it would just toggle repeatedly without any control. But if we could somehow limit the number of pulses to 8 or 16 (standard clock pulses for SPI communications) by counting the pulses once APIN starts toggling and then turning it off once it had reached a limit, then we would be in business! :-D

So has anybody got a solution? If you need any further explanation or details, please do not hesitate to ask.

Comments

  • pgbpsupgbpsu Posts: 460
    edited 2012-01-25 09:04
    I'm sure others who better understand the counters will have more elegant ways to do this but couldn't you simply turn the pin back to an input at some predetermined time to stop the output? If you know your toggle rate, you know how long it will take to output 8 or 16 bits so tell the system to wait for that time then switch toggle pin to an input. The problem with this is that SPIN doesn't respond that quickly so (aside from being a bit of hack) it wouldn't be possible for higher speeds. But if you're not going to get into PASM you probably won't be shifting bits onto the DATA pin that quickly anyway?
  • Tracy AllenTracy Allen Posts: 6,664
    edited 2012-01-25 09:11
    I posted an OBEX object that does what you are asking for, I think.
    NCOburst.spin
  • frank freedmanfrank freedman Posts: 1,983
    edited 2012-01-25 18:22
    Hi guys,

    I have a quick question that I hope you can help with. Basically I am trying to toggle any given pin as fast as possible WITHOUT assembly. The problem I am having is that I want to control the amount of times it toggles.

    I am using a counter register to toggle a given pin as per the example shown in the AN001 apllication note in the 'Propeller Downloads' section. The code is shown below:
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    
    PUB Main
      NCO_single_ended_mode(13)
    
    PUB NCO_single_ended_mode (PinNo)
    ''NOTES:
    ''FRQA values:
    ''  $8000_0000 = 12.6 MHz?
    ''  $0666_6666 = 2 MHz
    ''  $0000_0218 = 10 Hz
    ''  $0000_006B = 2 Hz
      ' mode PLL BPIN APIN
      dira[PinNo] := 1 'Set APIN to output
      ctra := 100_000 << 23 + 1 << 9 + PinNo 'Establish mode and APIN (BPIN is ignored)
      frqa := $8000_0000 'Set FRQA so PHSA[31] toggles every clock
      repeat 'infinite loop, so counter continues to run
    

    With this code, I can toggle the output of pin 13 (or any pin specified) to toggle VERY fast. Much faster than the '!OUTA[PinNo]' command does. As assembly is out of the question for this program, I want to see if it is possible to configure the second Counter Register (or Counter Register B) of this cog to somehow monitor the output of APIN from Counter Register A. For example, if you take an SPI clock pulse and use this program for it, it would just toggle repeatedly without any control. But if we could somehow limit the number of pulses to 8 or 16 (standard clock pulses for SPI communications) by counting the pulses once APIN starts toggling and then turning it off once it had reached a limit, then we would be in business! :-D

    So has anybody got a solution? If you need any further explanation or details, please do not hesitate to ask.

    D.L.

    I used pasm to implement an interface to an MCP3201. The actual clock pulses were driven by a pin tied to the counter, but used PASM instructions to count the number of bits read out and terminate the count. Not quite what you are looking for. Perhaps it would be possible to set output of CTRA to Bpin and preset counter B to count down or up the desired number of counts and then use its apin intput to stop the counter A from pulsing until the Bcounter is reset and releases the counter A Apin to resume counting. Hmmm actually you may be able to do this with one counter after all. See if the Bpin can be the clock output, and then use Apin to start/stop the counter. May only let you stop on 2^n counts depending on how it is structured......need more reading.

    FF
  • Dantes LegacyDantes Legacy Posts: 16
    edited 2012-01-26 01:16
    @pgbpsu - Yes, you are correct that I could use that method to stop the pulses, but I was hoping for a method were I could continuously alter the frequency if needed. Also, I would guess that when you reach a certain toggle speed, the WAITCNT command will be too slow. Then things would get quite difficult (well for me at least).

    @Tracy Allen - Just tested your object out there and it is exactly what I am looking for! To use it for an SPI Clock signal, all I have to do is pull the pin down low again after the 'Make' Function like so:
    CON
      _clkmode = xtal1 + pll16x
      _xinfreq = 5_000_000
    OBJ
      Burst :       "NCOburst"
         
    PUB Main | Pin, Hertz, Cycles
      Pin := 0
      Hertz := 5
      Cycles := 8
    
      repeat 'output a clk signal that pulses 8 times at a frequency of 5 Hz.
        Burst.make(Pin, Hertz, Cycles)
        OUTA[Pin]~
        waitcnt(clkfreq + cnt)
    
    

    Once this basic model is sped up, it should do exactly what I need. Thanks very much for your hard work!

    @ frank freedman - Thanks very much for your thoughts. I will try that out also. I am atually using all 8 cogs at the moment, so Pasm is out of the question for now. I only recently started trying to do anything like this with the counters...yesterday actually. So it may take another bit of reading on my end to understand fully how to impllement what you have suggested.

    In any case, I will mark this topic as solved. Thanks very much for your help everybody! :thumb:
Sign In or Register to comment.