Shop OBEX P1 Docs P2 Docs Learn Events
PropC confusion — Parallax Forums

PropC confusion

Beavis3215Beavis3215 Posts: 229
edited 2016-10-10 14:50 in General Discussion
[
/*
  3 button calculator
   
*/
#include "simpletools.h"                      // Include simple tools

int main()                                    // Main function
{
  set_directions(9,4,0b111111);                 // Output Lights
  set_directions(23,21,000);                  // Input Buttons
  
  static char a;
  int button1 = input(21);
  int button2 = input(22);
  int button3 = input(23);                  

 
  while(1)
  {
    
       while(button2 == 0)                    // Enter first operand                   
       {
         if (button1 == 1)
         {
           set_outputs(9,4,1 + get_outputs(9,4));
           pause(300);
         }
       }
       a = get_outputs(9,4);
       set_outputs(9,4,0);                    
      while(button3 == 0)                    // Enter second operand
      {
        if (button1 == 1)
        {
          set_outputs(9,4,1 + get_outputs(9,4));
          pause(300);
        }
        
      }
      set_outputs(9,4,a + get_outputs(9,4));
                                   
  }  
}


This code works with format "while input(2) == 0", Why can't I substitute button2 in the above code?
«13

Comments

  • Probably because button2 = input(22). So which input is the actual button #2 connected to, 2 or 22 ?
  • I had a typo

    /*
      3 button calculator
       
    */
    #include "simpletools.h"                      // Include simple tools
    
    int main()                                    // Main function
    {
      set_directions(9,4,0b111111);                 // Output Lights
      set_directions(23,21,000);                  // Input Buttons
      
      static char a;                 
    
     
      while(1)
      {
        
           while(input(22) == 0)                    // Enter first operand                   
           {
             if (input(21) == 1)
             {
               set_outputs(9,4,1 + get_outputs(9,4));
               pause(300);
             }
           }
           a = get_outputs(9,4);
           set_outputs(9,4,0);                    
          while(input(23) == 0)                    // Enter second operand
          {
            if (input(21) == 1)
            {
              set_outputs(9,4,1 + get_outputs(9,4));
              pause(300);
            }
            
          }
          set_outputs(9,4,a + get_outputs(9,4));
                                       
      }  
    }
    


    This code works, the first example does not.
  • PublisonPublison Posts: 12,366
    edited 2016-10-10 17:17
    Please refrain from posting the same questions in two separate threads. It will confus people trying to answer the questions.


    http://forums.parallax.com/discussion/165150/propeller-c-manual#latest

  • Beavis3215Beavis3215 Posts: 229
    edited 2016-10-16 19:23
    #include "simpletools.h"                      // Include simple tools
    void del(int time)
    {
       waitcnt(time + CNT);
    }
    
    
    int main()                                    // Main function
    {
      set_direction(9,1);
      static char delay;
    
     
      for(int n = 1; n <= 10; n++) 
      {
        set_output(9,1);
        del(100000);
        set_output(9,0);
        del(100000);
      }
         
              
    }
    
    Does anyone understand why pin 9 blinks one time and not 10?
  • Your delay times are only 1/800th of a second, so I'm not sure how you would see the blink. Your loop will run 10 times, which should generate 10 blinks.
  • You are correct. If I delay longer you can see them. The way it is now you see the combination of all 10 together. Thanks Again Dave.
  • I have been studying the C propeller.h library and I can't figure out the syntax of dira and outa which seem to be straight forward. I think that I don't fully understand the format of the propeller.h library. Can someone please give me an example use of dira and outa so that I can understand the library format better? I have been using set_direction and set_output but I want to understand the actual C code and not depend so much on simpletools.
  • DIRA and OUTA map directly to the DIRA and OUTA 32-bit registers. You simply treat them like standard 32-bit variables in C. So I'll help you rephrase your question so that you can better find the results for yourself, without having to wait for the forum to respond:

    "How do I manipulate individual bits of a variable in C?"

    Searching Google for that question brings you here, and the first hit is quite thorough (aka, LONG). So, I'll summarize:
    // Set Pin 1 (bit 0) high
    unsigned int pinMask = 0x01
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin 2 (bit 1) high
    unsigned int pinMask = 0x02
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin X (bit x - 1) high
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin X (bit x - 1) low
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA |= pinMask;
    OUTA &= ~pinMask; // This means invert all the bits in pinMask, and then do a bit-wise AND with OUTA
    
    // Set Pin X (bit x - 1) as an input
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA &= ~pinMask;
    

    Here's a short and concise article showing the bit operations: https://www.tutorialspoint.com/cprogramming/c_bitwise_operators.htm
  • I fully get this, but it looks different than the propeller.h reference. thanks for the help David. :)
  • DavidZemon wrote: »
    DIRA and OUTA map directly to the DIRA and OUTA 32-bit registers. You simply treat them like standard 32-bit variables in C. So I'll help you rephrase your question so that you can better find the results for yourself, without having to wait for the forum to respond:

    "How do I manipulate individual bits of a variable in C?"

    Searching Google for that question brings you here, and the first hit is quite thorough (aka, LONG). So, I'll summarize:
    // Set Pin 1 (bit 0) high
    unsigned int pinMask = 0x01
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin 2 (bit 1) high
    unsigned int pinMask = 0x02
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin X (bit x - 1) high
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin X (bit x - 1) low
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA |= pinMask;
    OUTA &= ~pinMask; // This means invert all the bits in pinMask, and then do a bit-wise AND with OUTA
    
    // Set Pin X (bit x - 1) as an input
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA &= ~pinMask;
    

    Here's a short and concise article showing the bit operations: https://www.tutorialspoint.com/cprogramming/c_bitwise_operators.htm

    Why do you use "1 << (x - 1)"? Shouldn't it be "1 << x" if you number pins start at zero?

  • David Betz wrote: »
    DavidZemon wrote: »
    DIRA and OUTA map directly to the DIRA and OUTA 32-bit registers. You simply treat them like standard 32-bit variables in C. So I'll help you rephrase your question so that you can better find the results for yourself, without having to wait for the forum to respond:

    "How do I manipulate individual bits of a variable in C?"

    Searching Google for that question brings you here, and the first hit is quite thorough (aka, LONG). So, I'll summarize:
    // Set Pin 1 (bit 0) high
    unsigned int pinMask = 0x01
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin 2 (bit 1) high
    unsigned int pinMask = 0x02
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin X (bit x - 1) high
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA |= pinMask;
    OUTA |= pinMask;
    
    // Set Pin X (bit x - 1) low
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA |= pinMask;
    OUTA &= ~pinMask; // This means invert all the bits in pinMask, and then do a bit-wise AND with OUTA
    
    // Set Pin X (bit x - 1) as an input
    unsigned int pinNumber = x;
    unsigned int pinMask = 1 << (x - 1);
    DIRA &= ~pinMask;
    

    Here's a short and concise article showing the bit operations: https://www.tutorialspoint.com/cprogramming/c_bitwise_operators.htm

    Why do you use "1 << (x - 1)"? Shouldn't it be "1 << x" if you number pins start at zero?

    Because in the first example, I'm not numbering the pins starting at zero. I should have explicitly brought attention to that, so thanks for bringing it up. @Beavis3215, most programmers will index at zero, so it would be better to do Pin 0 = bit 0. Then you don't have to do "x - 1" in code and whatnot.
  • //  wierd pwm program 1
    
    
    #include "simpletools.h"                      // Include simple tools
    void del(int time)
    {
       waitcnt(time + CNT);
    }
    
    
    int main()                                    // Main function
    {
      set_direction(9,1);
      set_direction(21,0);
      
      int time_on = 500000;
      int time_off = 600000;
      int debounce_time = 5000000;
      int sw_mask = 21;
     
     while(1)
     {
     waitpeq(1 << sw_mask, 1 << sw_mask);
     del(debounce_time);  
       
      for(int n = 500; n <= time_on; n = n + 4000) 
      {
        set_output(9,1);
        del(n);
        set_output(9,0);
        del(time_off);
      }
      
      set_output(9,1);
      waitpeq(1 << sw_mask, 1 << sw_mask);
      del(debounce_time);
     
       for(int n = time_on; n >= 500; n = n - 4000) 
      {
        set_output(9,1);
        del(n);
        set_output(9,0);
        del(time_off);
      }
      
      set_output(9,0);
      waitpeq(1 << sw_mask, 1 << sw_mask);
      del(debounce_time);
     
     }   
     
        
               
    }
    



    This program is supposed to brighten an LED connected to pin 9 when button connected to pin 21 is pressed, and dim LED when button is pressed again. The first program works. Incrementally I added Dira statments in program 2, but adding outa statments give a strange result. Any Ideas?


    // Wierd pwm program 2
    
    #include "simpletools.h"
                          
    void del(int time)
    {
       waitcnt(time + CNT);
    }
    
    
    int main()                                    // Main function
    {
      
      
      int time_on = 500000;
      int time_off = 600000;
      int debounce_time = 5000000;
      int sw_mask = 21;
      int out_mask = 9;
      
      DIRA |= (1 << out_mask);
      DIRA |= (0 << sw_mask);
     
     while(1)
     {
        waitpeq(1 << sw_mask, 1 << sw_mask);
        del(debounce_time);  
       
      for(int n = 500; n <= time_on; n = n + 4000) 
      {
        OUTA |= (1 << out_mask);
        del(n);
        OUTA |= (0 << out_mask);
        del(time_off);
      }
      
       OUTA |= (1 << out_mask);
       waitpeq(1 << sw_mask, 1 << sw_mask);
       del(debounce_time);
     
       for(int n = time_on; n >= 500; n = n - 4000) 
      {
        OUTA |= (1 << out_mask);
        del(n);
        OUTA |= (0 << out_mask);
        del(time_off);
      }
      
      OUTA |= (0 << out_mask);
      waitpeq(1 << sw_mask, 1 << sw_mask);
      del(debounce_time);
     
     }   
     
        
               
    }
    
  • DIRA |= (0 << sw_mask);
    
    does not do what you want. In fact it does nothing; (x|0) is always just x, so that statement does not change DIRA.

    What you probably want is:
    DIRA &= ~(1<<sw_mask);
    
    You have to use OR (|) to set bits, and AND (&) to clear bits. The same mistake shows up in a bunch of places in that code.

    I suggest you look again carefully at the references above. They are quite helpful.
  • Incidentally, the spincvt tool (or spin2cpp) can be used to show the C code equivalent of some Spin code, which might be helpful for this sort of work.
  • You helped me more than you know.
  • Is there a time savings in using C code vs simpletools shortcuts?
  • Beavis3215 wrote: »
    Is there a time savings in using C code vs simpletools shortcuts?

    This is a bit of an odd question the way you worded it. It sounds like you might be trying to ask whether or not the Simple library is very fast at runtime? If that's the case, the answer is a reasonably emphatic no. But there's also the question of, "Does it matter?" For many cases, no. For many other cases, yes. The Simple library was built by Parallax to be easy for beginners, and it certainly achieves that. However, they gave up performance (and sometimes code size, and almost always flexibility) to achieve that.

    Unfortunately you don't have quite the range of library choices in the PropGCC world as you do in the Spin world. To my knowledge, the following libraries exist: Simple, PropWare, libpropeller, libArduino (previously libpropelleruino), and OmniaCreator. Normally this is where I get on my pedestal and tout the wonders of PropWare... but it was never intended to be used by first-time C programmers. There are some aspects, particularly language syntax features, that could be difficult for a beginner to keep straight.

    So, with that being said, I'd recommend you stick with the Simple library for the time being. If you are able to identify a specific spot in code that running too slow, work on optimizing only that one spot. Feel free to come back to the forums and ask about that one spot and how it might be optimized.
  • I think the question of using "C code vs simpletools" refers to setting bits in DIRA and OUTA. If you use the functions in simpletools the code must do a function call, which has some overhead. Also, the simpletools functions must manipulate the parameters to set or clear bits. This requires a few extra cycles as well. If you operate directly on DIRA and OUTA the generated code will just AND or OR a constant with the I/O register. In general, this is more efficient.

    There is some advantage to using the simpletools functions because it provides a level of abstraction to setting and clearing bits. It might make the code easier to read as well. The simpletools function names convey the meaning of the operation that is being performed, whereas using the & and | operators on DIRA and OUTA may not be as clear. However, you could define your own macros that do the same thing as the simpletools function, and they would be just as efficient as using & and | explicitly in the code.
  • Beavis3215 wrote: »
    Is there a time savings in using C code vs simpletools shortcuts?

    I ran some tests to see how long it took to switch a pin from high to low using different languages and techniques. The circuit and purpose to measure the overhead times for RC timing based on the tutorials in the Propeller Education Kit.

    The results are shown here: https://forums.parallax.com/discussion/comment/1375740/#Comment_1375740

    The setup and method are discussed at the top of the thread.

    The results show the specific code to make the transition.

    As a baseline PASM took only 6 clocks. Spin took from 592 to 643 clocks depending on method.

    C using CMM memory model (compact code) and the SimpleTools functions took the longest, 689 or 707 clocks. Using propeller.h the time was cut to 145 or 163 clocks (depending on specific method).

    Using LMM memory model, the timing was 129 or 147 clocks for SimpleTools, and 17 to 35 clocks for propeller.h

    There is a big time difference between the SimpleTools and propeller.h libraries for the reasons Dave mentioned. For fastest execution, use propeller.h with LMM (if the code fits in memory) or even with CMM. The difference is that with propeller.h, it will often be necessary to do more bit manipulations.

    It can also be seen why in other threads there have been contradictory statements comparing the speed of SPIN and Propeller C, some saying C is slower; others that it is faster
    (They are both right depending on specific usage.)

    Tom




  • twm47099 wrote: »
    The difference is that with propeller.h, it will often be necessary to do more bit manipulations.
    When would using propeller.h require more bit manipulations?

  • Let's also just take a look at the high(int pin) source code

    From here:
    void high(int pin)
    {
      int mask = 1 << pin;
      OUTA |= mask;
      DIRA |= mask;
    }
    

    So normally, to cycle an LED you might write:
    int main () {
      while (1) {
        high(16);
        low(16);
      }
      return 0;
    }
    

    And that's all fine and dandy. But you can keep 100% of your legibility and have very fast execution time if you write your own functions. You do not need to invoke DIRA and OUTA directly everywhere (like Dave Hein mentioned... except I'd rather let PropGCC optimize for me then use preprocessor macros)
    int get_pin_mask(int pinNumber) {
      return 1 << pinNumber;
    }
    
    void set_output(int pinMask) {
      DIRA |= pinMask;
    }
    
    void set_input(int pinMask) {
      DIRA &= ~pinMask;
    }
    
    void go_high(int pinMask) {
      OUTA |= pinMask;
    }
    
    void go_low(int pinMask) {
      OUTA &= ~pinMask;
    }
    
    int main () {
      int ledMask = get_pin_mask(16);
      set_output(ledMask);
      while(1) {
        go_high(ledMask);
        go_low(ledMask);
      }
      return 0;
    }
    
  • DavidZemon wrote: »
    Let's also just take a look at the high(int pin) source code

    From here:
    void high(int pin)
    {
      int mask = 1 << pin;
      OUTA |= mask;
      DIRA |= mask;
    }
    

    So normally, to cycle an LED you might write:
    int main () {
      while (1) {
        high(16);
        low(16);
      }
      return 0;
    }
    

    And that's all fine and dandy. But you can keep 100% of your legibility and have very fast execution time if you write your own functions. You do not need to invoke DIRA and OUTA directly everywhere (like Dave Hein mentioned... except I'd rather let PropGCC optimize for me then use preprocessor macros)
    int get_pin_mask(int pinNumber) {
      return 1 << pinNumber;
    }
    
    void set_output(int pinMask) {
      DIRA |= pinMask;
    }
    
    void set_input(int pinMask) {
      DIRA &= ~pinMask;
    }
    
    void go_high(int pinMask) {
      OUTA |= pinMask;
    }
    
    void go_low(int pinMask) {
      OUTA &= ~pinMask;
    }
    
    int main () {
      int ledMask = get_pin_mask(16);
      set_output(ledMask);
      while(1) {
        go_high(ledMask);
        go_low(ledMask);
      }
      return 0;
    }
    
    Looks like a good approach.

  • Beavis3215Beavis3215 Posts: 229
    edited 2016-11-01 23:49
    t = -CNT;
     waitpeq(1 << crank, 1 << crank);   
     t = CNT - 544;
    



    In propgcc, is 544 still the number of ticks to run t = -cnt and t = cnt -544 as it is in spin?
  • Beavis3215 wrote: »
    t = -CNT;
     waitpeq(1 << crank, 1 << crank);   
     t = CNT - 544;
    



    In propgcc, is 544 still the number of ticks to run t = -cnt and t = cnt -544 as it is in spin?

    This is a very strange snippet of code. What are you trying to accomplish with this? I can see line two, you are waiting for the input on pin "crank" to go high. Are you trying to time how long it takes for the crank pin to go high?
  • /*
      EFI Project Code
      The flywhhel has 35 steel targets mounted to it.There is a large gap between target 35 and target 1.
      Inputs: Crankshaft position sensor connected to pin number 15.
      Outputs: Fire ignition coil connected to pin number 16. Binary target indicator connected to pins 23 - 18.
       
    */
    #include "simpletools.h"                      
    
    int main()                                    
    {
      int crank = 15;
      int coil = 16;
      int display = 23;
      int t = 0;
      int a = 0;
      int b = 0;
      
      DIRA &= ~(1 << crank);
      DIRA |= (1 << coil);
      DIRA |= (0b111111 << display);  //set pins 23 - 18 as outputs for target indicator
      
    
      
     
      
      
        
        // Routine to find target 1 on flywheel
        for (int n = 1; n <= 350; n = n + 1)
           {
             waitpeq(1 << crank, 1 << crank);
             waitpne(1 << crank, 1 << crank);  //wait for 350 targets to pass for rpm to stabilize
           }
           
        while(a > 5 * b)
           
          {         
           t = -CNT;
           waitpeq(1 << crank, 1 << crank);   //time low to high
           t = CNT - 544;
           a = t;
           
           waitpne(1 << crank, 1 << crank);
           
           t = -CNT;
           waitpeq(1 << crank, 1 << crank);   //time low to high
           t = CNT - 544;
           b = t;                             
         }                                    //upon leaving loop,a is the low to high time between 2 close targets 
         
           waitpne(1 << crank, 1 << crank);
         
        while(b < 5 * a)
        
          {
            t = -CNT;
            waitpeq(1 << crank, 1 << crank);   //time low to high
            t = CNT - 544;
            b = t;
          }        
        
                                              //upon leaving loop, crank is high on target number 1      
      }  
    
  • Here's some 36-1 code that's currently working on a generator application. I think it's the latest revision! Counters are awesome, that is all.. :-) Of course, it requires another cog to toggle injector and ign outputs w/ appropriate injector opening times and coil charge times calculated in the other cog.
    void decoder(void *par)
    {
        int32_t miss_gap = 0;
        int32_t teeth_seen_post_miss_tooth_gap = 0;
        uint32_t cur_phsa = 0;
        int32_t current_tooth_cnt = 0;     // current tooth cnt.
        int32_t current_gap = 0;
        int32_t last_tooth_cnt = 0;     // last tooth cnt.
        int32_t deg_cnt;
        int32_t a3;
        DIRA |= 0 << pip_pin;                    // Set to input
        CTRA = (0b01010<<26)+pip_pin;       // Set CTRA to PosEdge mode
        FRQA = 1;                           // Adds 1 to PHSA on each rising edge
    
        while(1) {
            /* Wait until missing tooth */
            while ( PHSA == cur_phsa);                     // Wait for posedge
            current_tooth_cnt = CNT;                       // Get CNT
            cur_phsa = PHSA;                               // Update cur_phsa
            current_gap = current_tooth_cnt - last_tooth_cnt;            // Get current gap
            if ((current_gap > miss_gap) && (teeth_seen_post_miss_tooth_gap != 0))    // true if gap is > calc'd missing tth gap && prev iteration was not a double miss_gap detect
            {
                cur_ang_10 = 0;
                teeth_seen_post_miss_tooth_gap = 0;
                current_gap = current_gap/2;                // Compensates for previous missing tooth gap
            } else                                          // All other gaps handled here
            {
                if (teeth_seen_post_miss_tooth_gap <34)
                {
                    cur_ang_10 = cur_ang_10+10;                 // We're 10* further
                    miss_gap = current_gap * 1750;              // 1/2 Updates calc'd miss_gap on the fly; only update miss_gap w/ reg gap data
                    miss_gap = miss_gap / 1000;                 // 2/2 1750/1000: integer form of *1.75
                    teeth_seen_post_miss_tooth_gap++;           // Increment # teeth seen after missing tooth gap
                }
            }
            angle_cnt[cur_ang_10] = current_tooth_cnt;          // Store CNT for 0,10,20,etc...
            deg_cnt = (((current_gap*1024)/10)/1024);           // deg_cnt is CNTs per degree at current rotational speed
            if (cur_ang_10 == 340)                              // There is no tooth for 350 so calc next 20 degrees
            {
                a3 = 20;
            }
            else
            {
                a3 = 10;
            }
            for (int a2 = 1; a2 < a3; a2++)
            {
                angle_cnt[cur_ang_10 + a2] = (angle_cnt[cur_ang_10 + a2 - 1] + deg_cnt);
            }
            last_tooth_cnt = current_tooth_cnt;                      // Store current to last for next tooth gap calc
        }
    }
    
  • My strategy is to keep accurate bookkeeping of crank position (using a counter). I will make a data map on a ROM using modified sensor data to be used for the address for the location where ignition target (timing), and injector target and time are stored, for each allowed combination of sensor data. In this way all calculating is prefabricated as a bit pattern on a ROM. My C ability for now is crude, but I am learning. My plan is to reinvent the wheel, just for the fun of it, and apply it to a Honda GCV 190 engine. I will be working on this for years to come.
  • Cool. My test mule, so to speak is a Honda GX200.
  • AribaAriba Posts: 2,682
    edited 2016-11-03 00:38
    Beavis3215 wrote: »
    t = -CNT;
     waitpeq(1 << crank, 1 << crank);   
     t = CNT - 544;
    


    In propgcc, is 544 still the number of ticks to run t = -cnt and t = cnt -544 as it is in spin?

    No C is faster. How much faster depends on the Memory Model and the Optimization, so no constant value to subtract.

    Your example code will not work as is, I think you meant: t += CNT - 544;

    To get the clocks to subtract just put no code between the begin and end of the time measure:
        t = CNT;
        t = CNT - t;   //now t holds the amount of ticks to subtract.
    

    Andy




  • Beavis3215Beavis3215 Posts: 229
    edited 2016-11-03 11:16
    That was my typo, thanks Andy for the help.
Sign In or Register to comment.