Shop OBEX P1 Docs P2 Docs Learn Events
<simpletools.h> long count ( int pin, long duration) doubles expected result? — Parallax Forums

<simpletools.h> long count ( int pin, long duration) doubles expected result?

ganzuulganzuul Posts: 8
edited 2014-10-25 16:12 in Propeller 1
When I use count(0,1000) to measure the 1000 baud square wave that my oscilloscope puts out, I get a return value which not only varies ~10%, but is double the value I expected. i.e. I get ~2000 when I expect ~1000.

Is this a bug? What is the maximum pulse rate I can measure this way?

Reference:
https://propsideworkspace.googlecode.com/hg-history/029efb9bf270758003c0a67571d1cbe4cc9986b5/Learn/Simple%20Libraries/Utility/libsimpletools/html/simpletools_8h.html#a20a9d97de9777b12cfd9353a83ac21cb

I have a really hard time interpreting the .asm rendition of the code:
GNU assembler version 2.21 (propeller-elf)
     using BFD version (propellergcc_v1_0_0_2408) 2.21.
 options passed    : -lmm -ahdlnsg=lmm/PulseMonitor.asm 
 input file        : C:\Users\n\AppData\Local\Temp\ccIBm3CJ.s
 output file       : lmm/PulseMonitor.o
 target            : propeller-parallax-elf
 time stamp        : 

   1                      .text
   2                  .Ltext0
   3                      .data
   4                      .balign    4
   5                  .LC0
   6 0000 25640A00         .ascii "%d\12\0"
   7                      .text
   8                      .balign    4
   9                      .global    _main
  10                  _main
  11                  .LFB1
  12                      .file 1 "PulseMonitor.c"
   1:PulseMonitor.c **** /*
   2:PulseMonitor.c ****   PulseMonitor.c
   3:PulseMonitor.c **** */
   4:PulseMonitor.c **** 
   5:PulseMonitor.c **** #include "simpletools.h"                      
   6:PulseMonitor.c ****  
   7:PulseMonitor.c **** long clocks = 0;
   8:PulseMonitor.c **** 
   9:PulseMonitor.c **** int main()                                    
  10:PulseMonitor.c **** { 
  13                      .loc 1 10 0
  14 0000 0400FC84         sub    sp, #4
  15                  .LCFI0
  16 0004 00003C08         wrlong    lr, sp
  17                  .LCFI1
  18 0008 0800FC84         sub    sp, #8
  19                  .LCFI2
  11:PulseMonitor.c ****   clocks = count(0, 1000);
  20                      .loc 1 11 0
  21 000c 00007C5C         mvi    r1,#1000
  21      E8030000 
  22 0014 0000FCA0         mov    r0, #0
  23 0018 00007C5C         lcall    #_count
  23      00000000 
  24 0020 00007C5C         mvi    r7,#_clocks
  24      00000000 
  25 0028 00003C08         wrlong    r0, r7
  12:PulseMonitor.c ****   print("%d\n",clocks);
  26                      .loc 1 12 0
  27 002c 00007C5C         mvi    r7,#.LC0
  27      00000000 
  28 0034 00003C08         wrlong    r7, sp
  29 0038 0000BCA0         mov    r7, sp
  30 003c 0400FC80         add    r7, #4
  31 0040 00003C08         wrlong    r0, r7
  32 0044 00007C5C         lcall    #_print
  32      00000000 
  13:PulseMonitor.c **** }...
  33                      .loc 1 13 0
  34 004c 0000FCA0         mov    r0, #0
  35 0050 0800FC80         add    sp, #8
  36 0054 0000BC08         rdlong    lr, sp
  37 0058 0400FC80         add    sp, #4
  38 005c 0000BCA0         mov    pc,lr
  39                  .LFE1
  40                      .global    _clocks
  41                      .section    .bss
  42                      .balign    4
  43                  _clocks
  44 0000 00000000         .zero    4
  82                  .Letext0
  83                      .file 2 "C:/Users/n/Documents/SimpleIDE/Learn/Simple Libraries/TextDevices/libsimpletext/simpletex
DEFINED SYMBOLS
C:\Users\n\AppData\Local\Temp\ccIBm3CJ.s:10     .text:00000000 _main
C:\Users\n\AppData\Local\Temp\ccIBm3CJ.s:14     .text:00000000 L0
C:\Users\n\AppData\Local\Temp\ccIBm3CJ.s:43     .bss:00000000 _clocks
                            .data:00000000 .LC0
                     .debug_frame:00000000 .Lframe0
                            .text:00000000 .LFB1
                    .debug_abbrev:00000000 .Ldebug_abbrev0
                            .text:00000000 .Ltext0
                            .text:00000060 .Letext0
                      .debug_line:00000000 .Ldebug_line0
                            .text:00000060 .LFE1
                       .debug_loc:00000000 .LLST0
                      .debug_info:00000000 .Ldebug_info0

UNDEFINED SYMBOLS
sp
lr
__LMM_MVI_r1
r0
__LMM_CALL
_count
__LMM_MVI_r7
r7
_print
pc

The C code:
/*
  PulseMonitor.c
*/

#include "simpletools.h"                      
 
long clocks = 0;

int main()                                    
{ 
  clocks = count(0, 1000);
  print("%d\n",clocks);
}

Comments

  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-24 12:09
    The documentation isn't too clear on this, and I could be reading the source code wrong, but it looks like the second parameter of `count()` is pretty odd.

    Source
    19 long count(int pin, long duration)            // count function definition
       20 {
       21   /*
       22   if(!st_pauseTicks)                             // If global dt not initialized
       23   {
       24     //set_io_dt(CLKFREQ/1000000);             // Initialize dt
       25     if(st_pauseTicks == 0) set_pause_dt(CLKFREQ/1000);
       26     set_io_timeout(CLKFREQ/4);                // Initialize timeout
       27   }
       28   */
       29   int state = 1;                              // Initialize state to 1
       30   long transitions;                           // Declare transitions var
       31   int ctr = (10 << 26) + pin;                 // Positive edge ctr config
       32   long tf = duration * st_pauseTicks;            // Set timeout
       33   int t = CNT;                                // Mark current time
       34   // Wait until pin matches state or timeout.
       35   while((input(pin) == state) && (CNT - t < tf));
       36   if(CTRA == 0)                               // If counter A unused
       37   {
       38     CTRA = ctr;                               // Start counter module
       39     FRQA = 1;                                 // Increment PHSA by 1 per edge
       40     t = CNT;                                  // Reset current time
       41     PHSA = 0;                                 // Clear phase accumulator
       42     while(CNT - t < tf);                      // Wait for timeout
       43     CTRA = 0;                                 // Stop the counter
       44     transitions = PHSA;                       // Record pos edge crossings
       45   }
       46   else if(CTRB == 0)                          // If CTRA in use, use CTRB
       47   {
       48     CTRB = ctr;                               // Equivalent to CTRA block
       49     FRQB = 1;
       50     t = CNT;
       51     PHSB = 0;
       52     while(CNT - t < tf);
       53     CTRB = 0;
       54     transitions = PHSB;
       55   }
       56   else                                        // If both counters in use
       57   {
       58     transitions = -1;                         // Return -1.
       59   }
       60   return transitions;                         // Return transitions
       61 }
    

    Take a look at line 32. Documentation on `st_pauseTicks` says it defaults to 1/4 second, which would imply that if you call `count(0, 1)`, you should expect to get a return value of 250 for a 1000 baud signal.

    0.25 * 1000 = 250 seconds. That will overflow the `tf`.
  • ganzuulganzuul Posts: 8
    edited 2014-10-24 12:30
    That... is... strange. I counted a duration of 10 000 to about 10 seconds, so I presumed...

    Are you sure you're not thinking of st_timeout?
    st_timeout = 250*st_msTicks; in http://david.zemon.name/PropWare/timeTicks_8c_source.html (Thanks for the link!)

    And did I miss something in calculating tf in my head? I don't feel a long should overflow at these values...
  • kuronekokuroneko Posts: 3,623
    edited 2014-10-24 12:34
    Works for me. Clock source being an on-chip counter (NCO, frqx = 53687 @80MHz). count(pin, duration) returns duration in this case.
  • ganzuulganzuul Posts: 8
    edited 2014-10-24 15:25
    Kuroneko could you reiterate on what you just said? I think you packed your data too densely for me. :(
  • kuronekokuroneko Posts: 3,623
    edited 2014-10-24 23:44
    ganzuul wrote: »
    Kuroneko could you reiterate on what you just said? I think you packed your data too densely for me. :(
    Sure, as I don't have external h/w for generating a pulse wave I programmed a cog counter (NCO mode) to generate a 1kHz square wave (frqx = 53687). The latter value is derived from the following equation: f = clkfreq*frqx/232 (see counter application note). This counter runs in the same cog as the count function which means I had to modify said function slightly to not use its braindead input(pin) call. The pin is tested directly with the pin mask (see below). With all that I get the expected number of low/high transitions. IOW a call to count(16, 1000) returns 1000, cutting the frqx value in half (lower frequency) will also half the returned value.
    /*
      PulseMonitor.c
    */
    
    #include "simpletools.h"                      
     
    long count_local(int pin, long duration) {      // count function definition
        [COLOR="#FF8C00"]int state = 1 << pin[/COLOR];                       // Initialize state to pin pattern
        long transitions = -1;                      // Declare transitions var with default response
        int ctr = (10 << 26) + pin;                 // Positive edge ctr config
        long tf = duration * st_pauseTicks;         // Set timeout
        int t = CNT;                                // Mark current time
    
        while (([COLOR="#FF8C00"]INA & state[/COLOR]) && (CNT - t < tf));    // Wait until pin matches state or timeout.
    
        if (!CTRA) {                                // If counter A unused
            CTRA = ctr;                             // Start counter module
            FRQA = 1;                               // Increment PHSA by 1 per edge
            t = CNT;                                // Reset current time
            PHSA = 0;                               // Clear phase accumulator
            while (CNT - t < tf);                   // Wait for timeout
            CTRA = 0;                               // Stop the counter
            transitions = PHSA;                     // Record pos edge crossings
        } else if (!CTRB) {                         // If CTRA in use, use CTRB
            CTRB = ctr;                             // Equivalent to CTRA block
            FRQB = 1;
            t = CNT;
            PHSB = 0;
            while (CNT - t < tf);
            CTRB = 0;
            transitions = PHSB;
        }
        return transitions;                         // Return transitions
    }
    
    int main(int argc, char **argv) {
        long clocks = 0;
    
        DIRA = 1 << 16;                             // pin 16 output
        CTRB = (4 << 26) | 16;                      // NCO on pin 16
        FRQB = 53687;                               // 1kHz
         
        waitcnt(CLKFREQ*3 + CNT);
        clocks = count_local(16, 1000);             // count for 1000 ms
        print("%d\n", clocks);
        
        exit(0);
    }
    
    That being said, are you sure your generated pulse wave has the right frequency?
  • ganzuulganzuul Posts: 8
    edited 2014-10-25 06:45
    I'm not certain of it, no. I'm actually getting completely different results now. The 1000kHz pulse returns ~86 000, and the signal I'm interested in measuring clocks in at ~1MHz higher than before; about 14.5MHz. Variance is still in the same order of magnitude which makes me really wonder about clock recovery.

    Perhaps it is time I scratch together the money for a real scope. I have been investigating a very cheap USB one called the DDS120, and the signal I'm trying to get from it is its Encode clock sent to the ADC. The device is cheap enough that one might leave it in a permanent installation, or upgrade from an RTL-SDR, but it needs new firmware. Three others have started to work on the same project and by now I'm barely keeping up with them.

    Thank you very much for your help! I'll study the code you posted in detail. =D
  • DavidZemonDavidZemon Posts: 2,973
    edited 2014-10-25 16:12
    ganzuul wrote: »
    I'm not certain of it, no. I'm actually getting completely different results now. The 1000kHz pulse returns ~86 000, and the signal I'm interested in measuring clocks in at ~1MHz higher than before; about 14.5MHz. Variance is still in the same order of magnitude which makes me really wonder about clock recovery.

    Perhaps it is time I scratch together the money for a real scope. I have been investigating a very cheap USB one called the DDS120, and the signal I'm trying to get from it is its Encode clock sent to the ADC. The device is cheap enough that one might leave it in a permanent installation, or upgrade from an RTL-SDR, but it needs new firmware. Three others have started to work on the same project and by now I'm barely keeping up with them.

    Thank you very much for your help! I'll study the code you posted in detail. =D

    We've had oscilloscope threads here before. There's lots of praise for both Propalyzer and Saleae's Logic line.
Sign In or Register to comment.