I took my old soft_uart module (on a LM4F120) and got it working on a pic16f684 to send a string under the nec protocol.
The basic set-up is to generate a 38Khz carrier signal via the CCP1 module on RC5/CCP1 pin. That signal is periodically grounded by RC0 controlled by tmr0 interrupt, to produce the desired '1' and '0'.
/tmr0 isr
void interrupt isr(void) {
T0IF = 0; //clear the flag
if (_nec_carrier) { //carrier was sent. now, short the output
if (_nec_mask & *_nec_ptr) TMR0=-NEC_TICK; //this is a 1 bit. followed by 560us
else TMR0=-NEC_TICKx3; //this is a 0 bit. followed by 560us x 3
NEC_OFF(); //short the output
_nec_carrier=0; //output has been shorted
_nec_mask = _nec_mask >> 1; //shift to the next bit
if (_nec_mask == 0) { //advance to the next char
_nec_mask = 0x80; //msb first
_nec_ptr+=1; //advance tot he next char
IO_FLP(OUT_PORT, OUT_PIN); //flip out_pin for debugging
};
if (*_nec_ptr==0) { //if no more char to be sent, stop the transmission
T0IE = 0; //stop the interrupt
_nec_ready=1; //nec ready
};
} else { //output has been shorted. now see if we can transmitt new data
//send the carrier signal
TMR0=-NEC_TICK; //load the offset for the carrier seignal
NEC_ON(); //send the carrier signal
_nec_carrier=1; //carrier has been sent
}
}
The set-up is a fire-and-forget type: the main loop looks to see if the nec module is ready. Once it is ready, it loads up the string to be sent and go about doing its other businesses.
while (1) {
if (nec_isready()) nec_send(nRAM); //if nec unit is ready, send data
}
The buffer, nRAM, contains the chars to be sent. And in this case, it is defined as:
uint8_t nRAM[11]={0x55, 0x22, 0xf8, 0x8f, 0}; //nec buffer, 10 digits max
So it is a typical C string.
In the ISR, I flipped RC2 to indicate the chars being sent.
The timing parameters are defined and calculated by the compiler so the code can be easily adopted to other mcus, including non-PIC ones. The same concept can be used to produce soft-peripherals, like spi, i2c, uart, etc.
Comparing to the polling approach, it has very low cpu load: about 3% in this case.