PropC confusion
Beavis3215
Posts: 229
[
This code works with format "while input(2) == 0", Why can't I substitute button2 in the above code?
/*
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?

Comments
/* 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.
http://forums.parallax.com/discussion/165150/propeller-c-manual#latest
#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?"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:
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); } }What you probably want is: 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.
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.
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.
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
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; }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 }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 } }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