Pommie said:Doing Var|=1 to set the bottom bit is probably the best way. Most compilers will compile this to a bsf instruction anyway.
Mike.
Edit, I am assuming that the bit will be clear after a Var<<1 instruction.
kchriste said:I believe it's as simple as this:
PORTAbits.RA0 = 1;
Check the header file for the PIC you are using. It's full of clues.
kchriste said:I believe it's as simple as this:
PORTAbits.RA0 = 1;
Check the header file for the PIC you are using. It's full of clues.
unsigned char var; // your 8-bit variable
//...
var = (var<<1)&0xFE + RC5;
If you want to 'force' the compiler to use specific instructions, you could use the #asm directive and mix C & assembly.Brian Hoskins said:If not, I guess I'll just revert to assembly for the set and clear bit operations.
eng1 said:Another option:
Code:unsigned char var; // your 8-bit variable //... var = (var<<1)&0xFE + RC5;
eng1 said:If you want to 'force' the compiler to use specific instructions, you could use the #asm directive and mix C & assembly.
Yes, RXx is the pin you're going to sample (ohh, you said RC5 type datastream! and RA0 is the I/O pin, I've got it now). I would suggest ANDing the byte just to ensure that the PIC will do what you expect. The code would be reliable without looking at the assembly code generated by the C compiler.Brian Hoskins said:Your suggestion is to AND with a mask which is perfectly reasonable and I was aware of its use, but I hoped there would be a more efficient way of doing it for embedded systems that I wasn't aware of. Your code makes sense to me though - I guess "RC5" is the I/O pin where the stream is sampled (in my case RA0)
#define IR_BIT PORTAbits.RA0
unsigned char i, irByte;
for (char i = 6; i > 0; i--)
{
irByte = irByte << 1; // will shift in a zero
irByte = irByte | IR_BIT;
}
3v0 said:Any pic will be fast compared to the IR stream. You do not have to choose the fastest code. Put your effort into making it readable and portable.
Code:#define IR_BIT PORTAbits.RA0 unsigned char i, irByte; for (char i = 6; i > 0; i--) { irByte = irByte << 1; // will shift in a zero irByte = irByte | IR_BIT; }
You could write the lines inside the loop as a single line and that would be OK.
In general terse C code is harder for the compiler to optimize and harder for you to debug.
// Title: RC5 IR Receive Program
// Author: Brian Hoskins
// Version: 0.1
// Date 01 March 2008
#include <pic.h>
unsigned char Timer = 0x00;
unsigned char Address = 0x00;
unsigned char Command = 0x00;
bit Sync = 0;
void display_data (void)
{
PORTB = Address; // Display Address Data on PortB
PORTC = Command; // Display Command Data on PortC
TMR0 = 0x00;
while (TMR0 != Timer) // Do nothing for a millisecond or so. This ensures that the comms line has returned
{ // high before going back to main (), otherwise main will think there is a new
} // incoming datastream (data_validate should throw that out anyway though)
}
void process_data (void)
// Collect Address Data
{
char i;
for (i = 6; i>0; i--)
{
{
while (RA0 != Sync) // Wait for RA0 to equal sync, then we are at sync point
{
}
TMR0 = 0x00; // Reset TMR0 then wait for it to equal Timer
while (TMR0 != Timer) // Do nothing until TMR0 == Timer
{
}
Address |= RA0; // Set bottom bit of Address to RA0. (using logical OR)
Address = Address << 1; // Shift Left Address
Sync = !RA0; // Set Sync to complement of RA0
}
}
Address = Address >> 1; // Address Shift correction
// Collect Command Data
for (i = 6; i>0; i--)
{
{
while (RA0 != Sync) // Wait for RA0 to equal sync, then we are at sync point
{
}
TMR0 = 0x00; // Reset TMR0 then wait for it to equal Timer
while (TMR0 != Timer) // Do nothing until TMR0 == Timer
{
}
Command |= RA0; // Set bottom bit of Command to RA0. (using logical OR)
Command = Command << 1; // Shift Left Command
Sync = !RA0; // Set Sync to complement of RA0
}
}
Command = Command >> 1; // Command Shift correction
display_data () ; // Display that data.
}
void data_validate (void)
// The purpose of this function is as follows;
// When this function is called it means PortA bit 0 has gone low, which indicates that there may be some incoming
// data. TMR0 is reset so that timing of the incoming data pulse is started. The function then waits for PortA bit0
// to return high again. The TMR0 value is then stored in Timer, and this value is tested to ensure that it falls within
// 20% of the 889uS duration of an RC5 communication pulse. If it is within spec, the processing function is called
// so that the data can be further processed. If it is ouside of the limits, the function returns to main(). The value
// of Timer is used as the timing for sampling of the data stream in process_data ().
// AUTHOR NOTE: What if RA0 never returns high? Program will get stuck. Function should timeout once TMR0 reaches
// a certain value (although if it never returns high there is a fault condition anyway)
{
TMR0 = 0x00; // Reset Timer to 0
while (RA0 == 0) // Wait for PortA bit 0 to return high
{
}
Timer = TMR0; // Store Timer value
if (Timer > 0x6F && Timer <0x9D) // Check Pulse duration was within 20% of that stated in RC5 protocol
{
Timer = Timer + (Timer/2); // After sync the process_data function must sample RA0 after 1.5 pulse durations. This will
// cause a sample to be taken in the middle of the required data pulse (which allows for a
// timing error either side
process_data () ;
}
}
void setup_hardware (void)
{
TRISC = 0x00; // Set all of Port C for output
TRISB = 0x00 ; // Set all of Port B for output
TRISA = 0x01 ; // Set bit 0 of Port A for input, the rest for output
OPTION = 0b10000100; // Set Option Reg for /32 Timer clocked on internal instructions
GIE = 0; // Disable all interrupts
ADCON1 = 0b00000111; // Disable A/D (otherwise you can't use RA0 for digital I/O)
}
void main (void)
{
setup_hardware () ; // Setup I/O ports and Registers etc
while (1)
{
while (RA0 == 1) // Do nothing while PortA bit 0 is high (wait for IR signal)
{ // AUTHOR NOTE: This would be better as an interrupt
}
data_validate () ;
}
}
#define IR_BIT PORTAbits.RA0
unsigned char irByte;
...
{
unsigned char i;
for (char i = 6; i > 0; i--)
{
irByte = irByte << 1; // will shift in a zero
irByte = irByte | IR_BIT;
}
....
}
I was pointing out that terse C code can use more memory when compiled then the plain Jane variety because the compiler has to untangle it prior to optimization.I agree that a significant effort should be put into making code portable and readable. However, I feel it is useful to avoid a mindset where you waste resources and time just because your application allows you to do so. I won't spend hours optimising code that I don't have to, but I will always try to consider the most economical way of doing something if I can. I think it's useful to get used to thinking that way. Someone should tell Microsoft about this concept.
889uS duration of an RC5 communication pulse
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?