If you *don't* have a copy of K&R 2nd ed, you can get by with
The C Book, 2nd ed. by Banahan, Brady & Doran. Its not as well organised but it covers the essentials fairly thoroughly.
Turn to the sections on logical and bitwise operators (2.6 and 2.9 in K&R, 3.3 and 2.8.2.3 in The C Book) and lookup the bitwise AND and logical negation operators. You will now be equipped to dissect
while(!(TMR0&0x80));
.
* First note the trailing
;, this while() loop has no 'payload' - all it does is spin on the spot while its condition is TRUE. The comment 'Wait for ....' confirms that is my intention.
* Now look in the innermost bracket.
Unfortunately XC8 doesn't define a bitfield for the highest bit of Timer 0 and, unlike any PIC with interrupts, there is no flag set when it rolls over. We need a bitmask to extract the highest bit. The mask is 0x80 and after ANDING with Timer 0 we have a value that is either 0 0r 0x80.
* However the requirement is to keep looping till that bit sets, so outside the inner brackets is the negation (NOT) operator. That converts 0x80 (or any other non-zero value) to 0 (FALSE) and 0 to 1 (TRUE).
XC8 is fairly smart, and even the free mode recognises this idiom as a test and loop on a single bit and optimises it to:
85 1FB l392:
86 ;main222.c: 6: while(!(TMR0&0x80));
87
88 1FB 7E1 btfss 1,7 ;volatile
89 1FC BFB goto l392
If I'd used the conceptually much simpler:
while(TMR0<0x80);
it would use far more instructions as it would need to load the constant into W, compare it with TMR0 and then test a STATUS flag to decide what to do:
85 1F9 l392:
86 ;main222.c: 6: while(TMR0<0x80);
87
88 1F9 C80 movlw 128
89 1FA 081 subwf 1,w ;volatile
90 1FB 703 skipc
91 1FC BF9 goto l392
You really have to grok the instruction set to get the best out of XC8 on these tiny devices.
The next chunk had a mistake, a missing semicolon in the if() ... else ...:
{ // LED blinking task
static unsigned char LEDtime=0; // LED timer in complete flickers
static unsigned char LEDcnt=MAXVOLTS; // LED counter for flicker
if(button) LEDtime=5; // five complete flicker cycles per button push
if(LEDtime) {
LEDtime--;
if(LEDcnt>BattVolts) GPIO=RED; else GPIO=BLUE;
if(!LEDcnt--) LEDcnt=MAXVOLTS; //reset flicker counter
}
}
The two
static unsigned char variable declarations declare local variables that are initialised on startup then retain their values from one invocation of the task block to the next.
if(button) LEDtime=5; waits for the flag button to be set by the button task, it then sets the flicker cycke count to five. The button task will clear the flag on the next pass so this only happens once per debounced press. Alternatively you could let the flag stay set as long as the button is held and the LED task would keep doing the flicker pattern.
if(LEDtime) {
LEDtime--; checks LEDtime and if TRUE, decrements it to count down flicker cycles remaining.
if(LEDcnt>BattVolts) GPIO=RED; else GPIO=BLUE; turns on the red LED if the flicker counter is greater than the battery voltage otherwise it turns on the blue LED. It also turns off the other colour LED at the same time. I'm assuming there are only two output pins and each LED is on one of them.
Bugfix: inserted ; before else. if(!LEDcnt--) LEDcnt=MAXVOLTS; //reset flicker countercounts down for the flicker level and when it wraps around from zero, does what it says and resets it to MAXVOLTS, which Bruce suggested should be 73 in post#38.