Shop OBEX P1 Docs P2 Docs Learn Events
Question About square_wave() — Parallax Forums

Question About square_wave()

photomankcphotomankc Posts: 943
edited 2013-10-17 20:42 in Learn with BlocklyProp
I am working providing a programmable clock for a couple of boards of mine. To that end I was using the square_wave function from simpletools.h and ran into something weird.

First thing was that changing the frequency on the fly seemed to only work sporadically. I was no able to nail down a pattern but in general what happens is that the frequency doesn't change every time unless I follow this pattern:

square_wave(1,0,7000000);
square_wave_stop();
square_wave(1,0,7000000);
...
square_wave(1,0,8000000);
square_wave_stop();
square_wave(1,0,8000000);



If I just do this:

square_wave(1,0,7000000);
square_wave(1,0,8000000);

Sometimes it works. But often it doesn't. The function is called but the frequency doesn't always change. However, If I use the "set it - stop it - set it again" pattern then the frequency changes properly every time. Seems like that shouldn't be required. Has anyone else run into this? My current project is a little complicated to reproduce but if if would help I can post code up.

Comments

  • kuronekokuroneko Posts: 3,623
    edited 2013-10-14 22:17
    I suspect it has something to do with how the code works (i.e. starting a separate cog doing the work). If you don't use your local counters you may try this (untested) replacement:
    void square_wave(int pin, int channel, int freq) {
      int ctr, frq;
      square_wave_setup(pin, freq, &ctr, &frq);
      if(!channel) {   // 0
        if (freq) {	   // enabled
          FRQA  = frq;
          CTRA  = ctr;
          DIRA |= (1 << pin);
        } else {       // disabled
          CTRA  = 0;
          DIRA &= ~(1 << pin);
        }
      } else {         // 1
        if (freq) {	   // enabled
          FRQB  = frq;
          CTRB  = ctr;
          DIRA |= (1 << pin);
        } else {       // disabled
          CTRB  = 0;
          DIRA &= ~(1 << pin);
        }
      }  
    }
    
  • photomankcphotomankc Posts: 943
    edited 2013-10-16 07:55
    I'll dig into the library code on that a bit deeper. I may try to clone a version that does not spawn a cog since that seems like a waste if the current cog has availiable counters. It does appear that the frequency setting is not exactly simple from looking at the functions in place in squareWave.c
  • kuronekokuroneko Posts: 3,623
    edited 2013-10-16 08:08
    photomankc wrote: »
    It does appear that the frequency setting is not exactly simple from looking at the functions in place in squareWave.c
    It's the same as in Synth.spin. HTH
  • edited 2013-10-17 14:59
    Thanks for explaining the problem. CTR.spin is the object that both libraries are based on, and it seems to be exhibiting the same behavior (unexpected halts over 250-ish kHz). We'll take a closer look and let you know.

    Here is a function you can add to squareWave.c to make it use the calling cog's counter modules. Make sure to recompile the libsimpletools.side project for the memory model you want to use after adding it. Also, keep in mind that if you use it with both of the calling cog's counter modules, it will disable pulse_in, pulse_out, rc_time and some others. They all block execution until they return, which is why they are allowed in the same cog. The "set it and forget it" counter functions like square_wave, pwm, and servo_* all have to launch into other cogs to prevent this conflict since that didn't seem like a fair caveat to throw at beginners. If it wasn't part of the Learn folder, I would have focused more on optimization over ease of use.
    // Add to simpletools.h
    
    void square_wave_inline(int pin, int channel, int freq);
    
    // Add to squareWave.c
    
    void square_wave_inline(int pin, int channel, int freq)
    {
      int ctr, frq;
      square_wave_setup(pin, freq, &ctr, &frq);
      if(!channel)
      {
        ctra = ctr;
        frqa = frq;
        if(pin < 0)
        {
          pin = -pin;
          ctra = 0;
          frqb = 0;
        }
      }
      else 
      {
        ctrb = ctr;
        frqb = frq;
        if(pin < 0)
        {
          pin = -pin;
          ctrb = 0;
          frqb = 0;
        }
      }  
    
      if(ctra != CTRA)
      {
        if(CTRA != 0)
        {
          pin = CTRA & 0b111111;
          DIRA &= ~(1 << pin);
        }
    
        CTRA = ctra;
    
        if(ctra != 0)
        {
          pin = CTRA & 0b111111;  
          DIRA |= (1 << pin);
        }  
      }
    
      if(frqa != FRQA) FRQA = frqa;    
      
      if(ctrb != CTRB)
      {
        if(CTRB != 0)
        {
          pin = CTRB & 0b111111;
          DIRA &= ~(1 << pin);
        }
    
        CTRB = ctrb;
        FRQB = frqb;              
    
        if(ctrb != 0)
        {
          pin = CTRB & 0b111111;  
          DIRA |= (1 << pin);
        }  
      }
      if(frqb != FRQB) FRQB = frqb;    
    }
    
  • edited 2013-10-17 16:55
    Alright, well, it turned out that my scope's HF reject setting was on. The propeller was merrily generating the higher frequency signals, but my scope was filtering them out after one trigger.

    The square_wave_inline function in the previous post works fine now for all counter module frequencies now (and does not launch another cog).

    ...and there was a bug in the square_wave_cog function that was preventing the frequency changes from post #1. Here is the corrected version, and please accept my apologies for any delays this bug may have caused in your project.
    void square_wave_cog(void *par)
    {
      int pin;
      while(1)
      {
        if(ctra != CTRA)
        {
          if(CTRA != 0)
          {
            pin = CTRA & 0b111111;
            DIRA &= ~(1 << pin);
          }
    
          CTRA = ctra;
          FRQA = frqa;    
    
          if(ctra != 0)
          {
            pin = CTRA & 0b111111;  
            DIRA |= (1 << pin);
          }  
        }
    
        if(frqa != FRQA) FRQA = frqa;           // <-- Add
        
        if(ctrb != CTRB)
        {
          if(CTRB != 0)
          {
            pin = CTRB & 0b111111;
            DIRA &= ~(1 << pin);
          }
    
          CTRB = ctrb;
          FRQB = frqb;              
    
          if(ctrb != 0)
          {
            pin = CTRB & 0b111111;  
            DIRA |= (1 << pin);
          }  
        }
    
        if(frqb != FRQB) FRQB = frqb;           // <-- Add
    
      }
    }
    
  • photomankcphotomankc Posts: 943
    edited 2013-10-17 20:42
    No worries man. Thanks for looking into this.
Sign In or Register to comment.