Rev 277 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
// <editor-fold defaultstate="collapsed" desc="Configuration Bits">// PIC16F1825 Configuration Bit Settings// CONFIG1#pragma config FOSC = INTOSC // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)#pragma config WDTE = OFF // Watchdog Timer Enable (WDT software controlled)#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)#pragma config MCLRE = ON // MCLR Pin Function Select (MCLR/VPP pin function is digital input)#pragma config CP = OFF // Flash Program Memory Code Protection (Program memory code protection is disabled)#pragma config CPD = OFF // Data Memory Code Protection (Data memory code protection is disabled)#pragma config BOREN = ON // Brown-out Reset Enable (Brown-out Reset enabled)#pragma config CLKOUTEN = OFF // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)#pragma config IESO = ON // Internal/External Switchover (Internal/External Switchover mode is enabled)#pragma config FCMEN = ON // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)// CONFIG2#pragma config WRT = OFF // Flash Memory Self-Write Protection (Write protection off)#pragma config PLLEN = ON // PLL Enable (4x PLL enabled)#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)#pragma config BORV = LO // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)#pragma config LVP = OFF // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)// </editor-fold>#include "defines.h"#include "INTERRUPTS.h"#include "IO.h"#include "I2C1.h"#include "I2C2.h"#include "CPS.h"#include "TLC59116.h"#include "MCP23009.h"persistent uint8_t op_state;void Reset_Board(uint8_t next_state) {op_state = next_state;RESET();}uint8_t Get_Last_Reset(void) {uint8_t ret;if (PCONbits.nPOR == 0) {ret = RESET_POR;} else if (PCONbits.nBOR == 0) {ret = RESET_BOR;} else if (STATUSbits.nTO == 0) {ret = RESET_WDT;} else if (PCONbits.nRMCLR == 0) {ret = RESET_MCLR;} else if (PCONbits.STKOVF || PCONbits.STKUNF) {ret = RESET_STK;} else if (PCONbits.nRI == 0) {ret = RESET_RST;} else {ret = RESET_POR;}PCON = 0x0F;STATUSbits.nPD = 1;STATUSbits.nTO = 1;return ret;}uint8_t Read_Address(void) {uint8_t ret = I2C1_SLAVE_PREFIX;if (!I2C_ADDR_3_PORT)ret |= 0x08;if (!I2C_ADDR_2_PORT)ret |= 0x04;if (!I2C_ADDR_1_PORT)ret |= 0x02;if (!I2C_ADDR_0_PORT)ret |= 0x01;return ret;}BTN_STATUS btns;LED_VALUES leds = {0x00};int main(void) {uint8_t buffer[32];uint8_t result, length;uint8_t i2c_slave_addr;// uint8_t op_state;uint8_t i;// Set internal oscillator speed to 32MHzOSCCONbits.SPLLEN = 1; // 4x PLL enable (overwritten by config bits)OSCCONbits.IRCF = 0xE; // Base frequency @ 8MHzOSCCONbits.SCS = 0b00; // System clock determined by config bits// Initialize I/OIO_Init();uint8_t last_reset = Get_Last_Reset();if (last_reset == RESET_POR || last_reset == RESET_BOR ||last_reset == RESET_MCLR || last_reset == RESET_WDT ||last_reset == RESET_STK) {op_state = OP_STATE_IDLE;}// if (last_reset == RESET_RST) {// op_state = OP_STATE_ACTIVE;// }i2c_slave_addr = Read_Address();// Delay a bit to allow I2C lines to stabilize__delay_ms(10);// Initialize I2C1 in slave modeI2C1_DATA i2c1_data;I2C1_Init(&i2c1_data);I2C1_Configure_Slave(i2c_slave_addr);// Initialize I2C2 in master modeI2C2_DATA i2c2_data;I2C2_Init(&i2c2_data);I2C2_Configure_Master(I2C_1MHZ);CPS_DATA cps_data;CPS_Init(&cps_data);// Initialize interruptsInterrupt_Init();Interrupt_Enable();MCP23009_Init(&btns);MCP23009_Query();TLC59116_Init();// TLC59116_Write_All(&leds);if (op_state == OP_STATE_IDLE) {// IO_IOC_Enable();Idle_Animation();} else if (op_state == OP_STATE_ACTIVE) {uint8_t button_R = 0, button_L = 0;uint8_t dir_state = DIR_S;leds.single.LED_S = DIR_BRIGHTNESS;TLC59116_Write_All(&leds);while (1) {// Check if an I2C message was receiveddo {result = I2C1_Get_Status();} while (!result);length = I2C1_Read_Buffer(buffer);if (length == 1 && buffer[0] == CMD_RESET) {Reset_Board(OP_STATE_IDLE);} else if (length == 1 && buffer[0] == CMD_ACTIVE) {Reset_Board(OP_STATE_ACTIVE);} else if (length == 17 && buffer[0] == CMD_SET_LEDS) {for (i = 0; i < 16; i++) {leds.w[i] = buffer[i + 1];}// Reset the direction LEDsif (dir_state == DIR_S)leds.single.LED_S = DIR_BRIGHTNESS;else if (dir_state == DIR_W)leds.single.LED_W = DIR_BRIGHTNESS;else if (dir_state == DIR_N)leds.single.LED_N = DIR_BRIGHTNESS;else if (dir_state == DIR_E)leds.single.LED_E = DIR_BRIGHTNESS;TLC59116_Write_All(&leds);}// Check if either capacitive buttons were pressedif (cps_data.btn_pressed[0] && button_R == 0) {// Right button went from unpressed -> presseddir_state = Direction_Rotate_CClockwise(dir_state);TLC59116_Write_All(&leds);}if (cps_data.btn_pressed[1] && button_L == 0) {// Left button went from unpressed -> presseddir_state = Direction_Rotate_Clockwise(dir_state);TLC59116_Write_All(&leds);}// Save the previous button statebutton_R = cps_data.btn_pressed[0];button_L = cps_data.btn_pressed[1];// Poll the hardware buttonsI2C2_Master_Restart(MCP23009_ADDR, MCP23009_GPIOA, 1);do {result = I2C2_Get_Status();} while (!result);length = I2C2_Read_Buffer(buffer);btns.w = buffer[0];// Change the direction according to the user's perspectiveif (dir_state == DIR_W) {uint8_t tmp = btns.BTN_R_S;btns.BTN_R_S = btns.BTN_R_W;btns.BTN_R_W = btns.BTN_R_N;btns.BTN_R_N = btns.BTN_R_E;btns.BTN_R_E = tmp;} else if (dir_state == DIR_E) {uint8_t tmp = btns.BTN_R_S;btns.BTN_R_S = btns.BTN_R_E;btns.BTN_R_E = btns.BTN_R_N;btns.BTN_R_N = btns.BTN_R_W;btns.BTN_R_W = tmp;} else if (dir_state == DIR_N) {uint8_t tmp = btns.BTN_R_S;btns.BTN_R_S = btns.BTN_R_N;btns.BTN_R_N = tmp;tmp = btns.BTN_R_E;btns.BTN_R_E = btns.BTN_R_W;btns.BTN_R_W = tmp;}}}}uint8_t Direction_Rotate_Clockwise(uint8_t dir_state) {uint8_t ret;switch (dir_state) {case DIR_S:leds.single.LED_S = 0x00;leds.single.LED_W = DIR_BRIGHTNESS;ret = DIR_W;break;case DIR_W:leds.single.LED_W = 0x00;leds.single.LED_N = DIR_BRIGHTNESS;ret = DIR_N;break;case DIR_N:leds.single.LED_N = 0x00;leds.single.LED_E = DIR_BRIGHTNESS;ret = DIR_E;break;case DIR_E:leds.single.LED_E = 0x00;leds.single.LED_S = DIR_BRIGHTNESS;ret = DIR_S;break;}return ret;}uint8_t Direction_Rotate_CClockwise(uint8_t dir_state) {uint8_t ret;switch (dir_state) {case DIR_S:leds.single.LED_S = 0x00;leds.single.LED_E = DIR_BRIGHTNESS;ret = DIR_E;break;case DIR_E:leds.single.LED_E = 0x00;leds.single.LED_N = DIR_BRIGHTNESS;ret = DIR_N;break;case DIR_N:leds.single.LED_N = 0x00;leds.single.LED_W = DIR_BRIGHTNESS;ret = DIR_W;break;case DIR_W:leds.single.LED_W = 0x00;leds.single.LED_S = DIR_BRIGHTNESS;ret = DIR_S;break;}return ret;}void Check_I2C_Idle(void) {uint8_t buffer[32];uint8_t result, length, i;// Check if an I2C message was receivedresult = I2C1_Get_Status();if (result) {length = I2C1_Read_Buffer(buffer);if (length == 1 && buffer[0] == CMD_RESET) {Reset_Board(OP_STATE_IDLE);} else if (length == 1 && buffer[0] == CMD_ACTIVE) {Reset_Board(OP_STATE_ACTIVE);}}}void Idle_Animation(void) {LED_VALUES leds = {0};uint8_t led_direction_bar[8] = {1,0,0,0,0,0,0,0};uint8_t led_direction_dir[8] = {1,0,0,0};uint8_t led_direction_ind[8] = {1,0,0,0};uint8_t led_8_high_thres = 0x80; // Max brightness of the middle sectionuint8_t led_8_next_thresh = 0x40; // Threshold to start the next LEDuint8_t led_4_high_thres = 0x80; // Max brightness of the side sectionsuint8_t led_4_next_thresh = 0x74; // Threshold to start the next LEDuint8_t i, next_led;for (i = 0; i < 16; i++) leds.w[i] = 0x00;while (1) {// Check to see if a new message was receivedCheck_I2C_Idle();// Update the LEDs in the middle sectionfor (i = 0; i < 8; i++) {// Change the LED brightness depending on its directionif (led_direction_bar[i] == 1) {leds.w[i]++;} else if (led_direction_bar[i] == 2) {leds.w[i]--;}// Change direction if peak brightness is reached// When the brightness reaches a middle threshold, start// increasing the brightness of the next LEDif (led_direction_bar[i] == 1 && leds.w[i] == led_8_high_thres) {led_direction_bar[i] = 2;} else if (led_direction_bar[i] == 1 && leds.w[i] == led_8_next_thresh) {next_led = (i == 7) ? 0 : i + 1;led_direction_bar[next_led] = 1;} else if (led_direction_bar[i] == 2 && leds.w[i] == 0x00) {led_direction_bar[i] = 0;}}// Update the LEDs in the right sectionfor (i = 0; i < 4; i++) {// Change the LED brightness depending on its directionif (led_direction_dir[i] == 1) {leds.w[i+8]++;} else if (led_direction_dir[i] == 2) {leds.w[i+8]--;}// Change direction if peak brightness is reached// When the brightness reaches a middle threshold, start// increasing the brightness of the next LEDif (led_direction_dir[i] == 1 && leds.w[i+8] == led_4_high_thres) {led_direction_dir[i] = 2;} else if (led_direction_dir[i] == 1 && leds.w[i+8] == led_4_next_thresh) {next_led = (i == 3) ? 0 : i + 1;led_direction_dir[next_led] = 1;} else if (led_direction_dir[i] == 2 && leds.w[i+8] == 0x00) {led_direction_dir[i] = 0;}}// Update the LEDs in the left sectionfor (i = 0; i < 4; i++) {// Change the LED brightness depending on its directionif (led_direction_ind[i] == 1) {leds.w[i+12]++;} else if (led_direction_ind[i] == 2) {leds.w[i+12]--;}// Change direction if peak brightness is reached// When the brightness reaches a middle threshold, start// increasing the brightness of the next LEDif (led_direction_ind[i] == 1 && leds.w[i+12] == led_4_high_thres) {led_direction_ind[i] = 2;} else if (led_direction_ind[i] == 1 && leds.w[i+12] == led_4_next_thresh) {next_led = (i == 3) ? 0 : i + 1;led_direction_ind[next_led] = 1;} else if (led_direction_ind[i] == 2 && leds.w[i+12] == 0x00) {led_direction_ind[i] = 0;}}// Write the LED values to the controllerTLC59116_Write_All(&leds);// Delay a bit to slow down the animation__delay_ms(1);}}