#include <p18cxxx.h>
#include <delays.h>
#include <stdlib.h>
#include <stdio.h>
#include <usart.h>
#include <timers.h>
#define MAX_EN PORTAbits.RA0
#define TX_MODE 1
#define RX_MODE 0
#define MY_ADDRESS 'a'
#define CM_CHANGE_POWER 100 // Change Power Source [0, 1, 2 ... ]
#define CM_UPDATE_TOGGLES 101 // Change Toggles to ones sent from Master
#define CM_UPDATE_DIMMERS 102 // Change Dimmers to ones sent from Master
#define CM_SEND_TOGGLES 103 // Send Toggles to Master
#define CM_SEND_DIMMERS 104 // Send Dimmers to Master
#define CM_WRITE_EEPROM 105 // Write to EEPROM sent from Master
#define CM_READ_EEPROM 106 // Send EEPROM to Master
#define CM_MASTER 107 // Master On/Off
#define ACK 200 // Acknowlegdment
#define TEST 201 // Acknowlegdment
#define RX_MODE 0 // RA 484 En pin
#define TX_MODE 1 // RA 484 En pin
#define B1 PORTDbits.RD0
#define B2 PORTDbits.RD1
#define B3 PORTDbits.RD2
#define B4 PORTDbits.RD4
#define B5 PORTDbits.RD5
#define B6 PORTDbits.RD6
#pragma config WDT = OFF, LVP = OFF, OSC = HS, DEBUG = OFF
unsigned char receive_count = 0; // Num of Bytes to receive from MASTER
unsigned char transmit_count = 0; // Num of Bytes to transmit from MASTER
unsigned char receive_bytes[5] = {0};
unsigned char transmit_bytes[5] = {0};
void ParseInstruction(unsigned char);
void senddata(unsigned char);
void SlaveSetting(void);
unsigned long timercount = 0;
void T0_handler (void);
#pragma code T0_interrupt = 0x18
void T0_int (void)
{
_asm goto T0_handler _endasm
}
#pragma code
#pragma interrupt T0_handler
void T0_handler (void)
{
}
/* ~~~~ Interrupt Handler ~~~~ */
void rx_handler (void);
#pragma code rx_interrupt = 0x08
void rx_int (void)
{
_asm goto rx_handler _endasm
}
#pragma code
#pragma interrupt rx_handler
void rx_handler (void)
{
unsigned char c;
unsigned char i,j = 0;
if(PIR1bits.RCIF == 1)
{
c = ReadUSART();
if(c != 68){return;} // Compare Address in NINE Bit mode
TMR0H = 0; // Reset Timer0 to 0x0000
TMR0L = 0;
PIE1bits.RCIE = 0; // Disable Serial Interrupt
INTCONbits.T0IF = 0;
INTCONbits.T0IE = 1; // Enable Timer0 Interrupt for timeouts
RCSTAbits.RX9 = 0; // Read data byte now (without Nine bit)
while(!DataRdyUSART());
c = ReadUSART(); // Read Instruction
ParseInstruction(c);
for(i = 0; i < receive_count; i++)
{
while(!DataRdyUSART());
receive_bytes = ReadUSART(); // Fill received bytes
}
MAX_EN = TX_MODE;
TXSTAbits.TX9 = 0;
//Delay10KTCYx(254);
Delay10KTCYx(254);
for(j = 0; j < transmit_count; j++)
{
senddata(0x11); // Transmit required bytes
Delay1KTCYx(1);
}
senddata(ACK);
Delay1KTCYx(1);
//while(!DataRdyUSART());
//putrsUSART((const far rom char *)"SLAVE 1!");
}
if(INTCONbits.T0IF == 1 && INTCONbits.T0IE == 1)
{
timercount++;
if(timercount > 3){SlaveSetting();PORTAbits.RA3 = ~PORTAbits.RA3;}
PORTAbits.RA2 = ~PORTAbits.RA2;
INTCONbits.T0IF = 0;
}
//else{return;}
SlaveSetting(); // Go back to becoming Slave
}
unsigned char button = 0;
void senddata(unsigned char data)
{
//while(BusyUSART());
USART_Status.TX_NINE = 0;
WriteUSART(data);
while(BusyUSART());
}
void sendaddress(unsigned char data)
{
//while(BusyUSART());
USART_Status.TX_NINE = 1;
WriteUSART(data);
while(BusyUSART());
}
void process(void)
{
switch(button)
{
case 1:
sendaddress(68);
break;
case 2:
sendaddress(66);
break;
case 3:
sendaddress(70);
break;
case 4:
senddata(68);
break;
case 5:
senddata(66);
break;
case 6:
senddata(70);
break;
}
button = 0;
}
void main(void)
{
unsigned char i;
//OSCCON = 0x70;
ADCON1 = 0x0F; // make all AN (analog) pins digital (for bit ref)
TRISB = 0b00000000;
TRISA = 0b00000000; // First 5 bits (RA0-RA4) are inputs
TRISC = 0b10000000; // Tx and Rx to input (Tx input as per datasheet)
TRISD = 0xFF;
PORTA = 0;
PORTB = 0; // BUS to be set to 0 before PORTC to avoid junk to latch
PORTC = 0b00000000;
PORTD = 0x00;
// Assumes FOSC = 4 Mhz, 9600 bps.
OpenUSART (
USART_TX_INT_OFF &
USART_RX_INT_ON &
USART_ASYNCH_MODE &
USART_NINE_BIT &
USART_CONT_RX &
USART_BRGH_HIGH, 25
);
OpenTimer0 (TIMER_INT_OFF & T0_SOURCE_INT & T0_16BIT & T0_PS_1_1);
MAX_EN = RX_MODE;
RCONbits.IPEN = 1; // Enable interrupt priority
//IPR1bits.RCIP = 1; // Enable all high priority interrupts
INTCONbits.GIEH = 1;
PIR1bits.RCIF = 0; // Clear Receive Interrupt Flag
while(1){
if(B1 == 1){button = 1;while(B1);}
if(B2 == 1){button = 2;while(B2);}
if(B3 == 1){button = 3;while(B3);}
if(B4 == 1){button = 4;while(B4);}
if(B5 == 1){button = 5;while(B5);}
if(B6 == 1){button = 6;while(B6);}
process();
//USART_Status.RX_NINE = 0;
}
}
void ParseInstruction(unsigned char ins)
{
receive_count = 0;
transmit_count = 0;
switch(ins)
{
case CM_CHANGE_POWER:
receive_count = 1;
break;
case CM_UPDATE_TOGGLES:
receive_count = 1;
break;
case CM_UPDATE_DIMMERS:
receive_count = 1;
break;
case CM_SEND_TOGGLES:
transmit_count = 1;
break;
case CM_SEND_DIMMERS:
transmit_count = 1;
transmit_bytes[0] = 0x10;
break;
case CM_WRITE_EEPROM:
receive_count = 2; // Address and Data
break;
case CM_READ_EEPROM:
receive_count = 1; // Address
transmit_count = 1; // Data
break;
case CM_MASTER:
receive_count = 1;
break;
}
}
void SlaveSetting(void)
{
timercount = 0;
INTCONbits.T0IE = 0; // Disable Timer0 Interrupt for timeouts
RCSTAbits.RX9 = 1;
TXSTAbits.TX9 = 1;
PIR1bits.RCIF = 0;
MAX_EN = RX_MODE;
PIE1bits.RCIE = 1; // Enable Serial Interrupt
}