C18 structure for 'bits'

Status
Not open for further replies.

Mike - K8LH

Well-Known Member
Been searching awhile now for example on how to use a C18 structure to emulate the basic "bit" access that BoostC includes automatically, that is;
Code:
  myvar.0 = 1;        // set bit 0 in variable "myvar" to '1'
Any help would be appreciated.

TIA, Mike, K8LH
 
Look here:
**broken link removed**

like btbass from there said:

"look at the Pic18F header files. They make extensive use of bitfields. You can learn a trick or two by studying the header files."

heh i must say C18 is the least documented compiler i ever saw lol
 
Last edited:


In my opinion the simplest way is to define two macros:
Code:
[COLOR=black]#define bitset(var,bitno) (var|=1<<bitno)[/COLOR]
[COLOR=black]#define bitclr(var,bitno) (var&=~(1<<bitno))[/COLOR]

These macros will be translated into 1-cycle assembly intrusctions by the compiler.
I use them with 8-bit variables.
 
Last edited:
Nice!!! Do you mind if i though that in my C18 PDF? Whats your name?

Its would be like:
Code:
#define SpecialBit 2
unsigned char MyVar;

MyVar = 0;
bitset(MyVar,SpecialBit);
Then :
"MyVar would be 0 to start then after the bitset command, MyVar equals 00000100."
 
Last edited:

I'm aware of the macros, thank you. Wouldn't help much if I wanted to do something like this though;
Code:
  mode.0 ^= 1;      ; toggle sideband mode
Probably just go back to BoostC. Thanks guys.
 
This works for x.b0 ^= 1;
Code:
typedef union {
  struct {
    unsigned b0:1; 
    unsigned b1:1; 
    unsigned b2:1; 
    unsigned b3:1;
    unsigned b4:1; 
    unsigned b5:1; 
    unsigned b6:1; 
    unsigned b7:1;
  };
  struct {
    unsigned asByte:8;
  };
}  bitByte;  
....
  bitByte x;

  x.b3=1;
  x.asByte = 0x55;
The downside is that you must say x.asByte=123 and that you have to say x.b0 instead of x.0. Neither is a big deal if you are used to structures.
The upside is that you can use variables on the RHS;

Generated asm
Code:
131:                 bitByte ii;
132:                 
133:                 ii.b3=1;
  0152    0E01     MOVLW 0x1
  0154    86DB     BSF 0xfdb, 0x3, ACCESS
134:                 
135:                 ii.asByte = 0x55;
  0156    52DE     MOVF 0xfde, F, ACCESS
  0158    0E55     MOVLW 0x55
  015A    6EDD     MOVWF 0xfdd, ACCESS
3v0
 
could you not fix the x.asByte=123 by simply defining it after?

like
Code:
#define MyVar x.asByte
MyVar=123;
 
It sounds like a good idea but the preprocessor will then change
MyVar.b0
to
MyVar.asByte.b0

could you not fix the x.asByte=123 by simply defining it after?

like
Code:
#define MyVar x.asByte
MyVar=123;
 
heh i know hence why i only stated it would fix x.asByte = 123 ;p;

Could you nest the b0 in the asByte?
 
Last edited:
I'm just trying to find a way to test and clear individual switch flag bits like I do in BoostC. Suggestions? Thanks.

Code:
#define swSet swflags.0
#define swUp swflags.1
#define swDn swflags.2


while(1)
{ while(swSet)            // while "set" mode
  if(swUp)                // if "up" switch press
  { swUp = 0;             // clear switch flag bit
    incvalue();           // bump value
  }
  if(swDn)                // if "dn" switch press
  { swDn = 0;             // clear switch flag bit
    decvalue();           // bump value
  }
}
 
Last edited:
How about simple ANDing? Note: i didnt test this out lol but seems fine in my head lol

Code:
while(1){ 
    while(swflags & (1<<swSet))         // while "set" mode
    if(swflags & (1<<swUp))             // if "up" switch press
    { 
        swflags = ~(1<<swUp);           // clear switch flag bit
        incvalue();                     // bump value
    }
    if(swflags & (1<<swDn))             // if "dn" switch press
    { 
        swflags = ~(1<<swDn);           // clear switch flag bit
        decvalue();                     // bump value
    }
}

Ill change it into something simpler 1 minute
 
Last edited:
Jason,

That will work perfectly with minor correction but it's not as clean or as intuitive as the BoostC example...
 
Last edited:
heh and i made this too:
Code:
#define bitset(var,bitno) (var|=1<<bitno);
#define bitclr(var,bitno) (var&=~(1<<bitno));

unsigned char bitchk(unsigned char var,char bitno){
    unsigned char tmp;
    tmp = var & (1<<bitno);
    return tmp;
}

while(1){ 
    while(bitchk(swflags,swSet))         // while "set" mode
    if(bitchk(swflags,swUp))             // if "up" switch press
    { 
        bitclr(swflags,swUp);           // clear switch flag bit
        incvalue();                     // bump value
    }
    if(bitchk(swflags,swDn))             // if "dn" switch press
    { 
        bitclr(swflags,swDn);           // clear switch flag bit
        decvalue();                     // bump value
    }
}
 
Last edited:
I'm just trying to find a way to test and clear individual switch flag bits like I do in BoostC. Suggestions? Thanks.
What was wrong with my suggestion ? I am not saying it is the greatest but is does what you asked for.
 
Last edited:
Hi 3v0,

Thank you very much for for showing me how to build the structure. Unfortunately, if I understand you correctly, accessing the variable as a byte becomes extremely clumsy (ie; x.asbyte = 0x55).

Right now the portion of my program that manipulates the switch flags variable as a byte works just fine in both BoostC and in C18 (the C18 code below looks almost identical to the BoostC version) so I don't want to muck up that part.

I really do appreciate the input guys... Thank you!!!

Mike

Code:
unsigned char swold = 0;        // switch state latch
unsigned char flags = 0;        // short switch flag bits
unsigned char flong = 0;        // long switch flag bits
unsigned char tmr1k = 0;        // 1 second timer
unsigned char tmr25 = 25;       //
unsigned char beep = 0;         //
unsigned char bctr = 32;        //

#pragma interrupt isr_hi

/****************************************************************/
/*  time from 'newhi' (press) to 'newlo' (release) determines   */
/*  which flag bit, short or long, is toggled                   */
/*                                                              */
/*  swnew.0  ___---___---___----------___----------___          */
/*  swold.0  ____---___---___----------___----------__          */
/*  delta.0  ___-__-__-__-__-_________-__-_________-__          */
/*  newhi.0  ___-_____-_____-____________-____________          */
/*  newlo.0  ______-_____-____________-____________-__          */
/*  flags.0  _______------____________________________ short    */
/*  slong.0  __________________________-------------__ long     */
/*                                                              */

void isr_hi()                   // 1 msec interrupts
{ unsigned char swnew;          //
  unsigned char delta;          //
  unsigned char newhi;          //
  unsigned char newlo;          //

  PIR1bits.TMR2IF = 0;          // clr timer2 interrupt flag

  if(beep)                      // if beep task running
  { if(!(beep&1))               // if beep is even (b0 = 0)
      PORTB ^= 1<<spkr;         // toggle speaker pin
    if(!--bctr)                 // if end of 32 msec count
    { bctr = 32;                // reset 32 msec timer and
      beep--;                   // decrement beep counter
    }                           //
  }                             //

  if(!--tmr25)                  // if 25 msec interval
  { tmr25 = 25;                 // reset for 25 msecs and...
    swnew = ~PORTC;             // sample active lo switches
    swnew &= 0b00000111;        // on RC2, RC1, and RC0 pins
    delta = swnew ^ swold;      // state changes (hi or lo)
    newhi = delta & swnew;      // new hi level changes
    newlo = delta & swold;      // new lo level changes
    swold = swnew;              // update switch state latch

    if(tmr1k)                   // if 1 second timer running
      if(!--tmr1k)              // dec it and if timed out
        beep = 4;               // task double beep feedback
    if(newhi)                   // if new press
    { tmr1k = 1000/25;          // start 1 second timer and
      beep = 2;                 // task single beep feedback
    }                           //
    if(newlo)                   // if new release
    { if(!tmr1k)                // if 1 second timeout
        flong ^= newlo;         // toggle 'long' switch flag
      else                      // otherwise
        flags ^= newlo;         // toggle 'short' switch flag
      tmr1k = 0;                // clear 1 second timer
    }                           //
  }                             //
}
 
Last edited:
Hi 3v0,

Thanks to your example (and patience) I think I figured it out and I'm able to keep my original BoostC variable names and macro names. Thank you.

Thank you all for the fine examples. I learned a lot from all of them.

Kind regards, Mike

Code:
[COLOR=Red]typedef union
{ struct
  { unsigned b0:1;
    unsigned b1:1;
    unsigned b2:1;
    unsigned b3:1;
    unsigned b4:1;
    unsigned b5:1;
    unsigned b6:1;
    unsigned b7:1;
  };
  struct
  { unsigned asbyte:8;
  };
} bitbyte;

bitbyte x;

#define flags x.asbyte      // switch flag bits
#define RunSw x.b0          // Motor on/off switch on RC0 (flags.b0)
#define DirSw x.b2          // Motor fwd/rev switch on RC2 (flags.b2)[/COLOR]

while(1)
{ if(RunSw)                 // if "Run" switch press
  { RunSw = 0;              // clear switch flag bit
    MotorOn ^= 1;           // toggle motor on/off pin
  }
}
 
Last edited:
If one used struct's to define the bits and coded using the struct members, it should work on both compilers. This allows one to avoid the boostC name.bit.
 
Last edited:
Yeah, I'm lookin' into that right now. Trying the following to access bits as sw.Run, sw.Jog, sw.Dir, and byte-wide access as sw.flags for parallel switch logic in ISR. I suppose I could get used to doing it this way, if I have to (grin).

Regards, Mike

Code:
typedef union
{ struct
  { unsigned Run:1;               // Run switch flag (sw on RC0)
    unsigned Jog:1;               // Jog switch flag (sw on RC1)
    unsigned Dir:1;               // Dir switch flag (sw on RC2)
    unsigned unused:5;            // spare/unused bits
  };
  struct
  { unsigned flags:8;             // byte wide flag access
  };
} bitbyte;

bitbyte sw;
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…