Subversion Repositories Code-Repo

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
260 Kevin 1
// <editor-fold defaultstate="collapsed" desc="Configuration Bits">
2
// PIC16F1825 Configuration Bit Settings
3
 
4
// CONFIG1
5
#pragma config FOSC = INTOSC    // Oscillator Selection (INTOSC oscillator: I/O function on CLKIN pin)
273 Kevin 6
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT software controlled)
260 Kevin 7
#pragma config PWRTE = OFF      // Power-up Timer Enable (PWRT disabled)
8
#pragma config MCLRE = ON       // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
9
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
10
#pragma config CPD = OFF        // Data Memory Code Protection (Data memory code protection is disabled)
11
#pragma config BOREN = ON       // Brown-out Reset Enable (Brown-out Reset enabled)
12
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
13
#pragma config IESO = ON        // Internal/External Switchover (Internal/External Switchover mode is enabled)
14
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)
15
 
16
// CONFIG2
17
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
18
#pragma config PLLEN = ON       // PLL Enable (4x PLL enabled)
19
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
20
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
21
#pragma config LVP = OFF        // Low-Voltage Programming Enable (High-voltage on MCLR/VPP must be used for programming)
22
// </editor-fold>
23
 
24
#include "defines.h"
25
#include "INTERRUPTS.h"
273 Kevin 26
#include "IO.h"
260 Kevin 27
#include "I2C1.h"
28
#include "I2C2.h"
29
#include "TLC59116.h"
30
#include "MCP23009.h"
31
 
273 Kevin 32
persistent uint8_t op_state;
260 Kevin 33
 
273 Kevin 34
void Reset_Board(uint8_t next_state) {
35
    op_state = next_state;
36
    RESET();
37
}
260 Kevin 38
 
273 Kevin 39
uint8_t Get_Last_Reset(void) {
40
    uint8_t ret;
41
    if (PCONbits.nPOR == 0) {
42
        ret = RESET_POR;
43
    } else if (PCONbits.nBOR == 0) {
44
        ret = RESET_BOR;
45
    } else if (STATUSbits.nTO == 0) {
46
        ret = RESET_WDT;
47
    } else if (PCONbits.nRMCLR == 0) {
48
        ret = RESET_MCLR;
49
    } else if (PCONbits.STKOVF || PCONbits.STKUNF) {
50
        ret = RESET_STK;
51
    } else if (PCONbits.nRI == 0) {
52
        ret = RESET_RST;
53
    } else {
54
        ret = RESET_POR;
55
    }
260 Kevin 56
 
273 Kevin 57
    PCON = 0x0F;
58
    STATUSbits.nPD = 1;
59
    STATUSbits.nTO = 1;
60
    return ret;
260 Kevin 61
}
62
 
63
uint8_t Read_Address(void) {
273 Kevin 64
    uint8_t ret = I2C1_SLAVE_PREFIX;
65
    if (!I2C_ADDR_3_PORT)
66
        ret |= 0x08;
67
    if (!I2C_ADDR_2_PORT)
68
        ret |= 0x04;
69
    if (!I2C_ADDR_1_PORT)
70
        ret |= 0x02;
71
    if (!I2C_ADDR_0_PORT)
72
        ret |= 0x01;
73
 
260 Kevin 74
    return ret;
75
}
76
 
273 Kevin 77
BTN_STATUS btns;
275 Kevin 78
LED_VALUES leds = {0x00};
273 Kevin 79
 
260 Kevin 80
int main(void) {
81
    uint8_t buffer[32];
82
    uint8_t result, length;
83
    uint8_t i2c_slave_addr;
273 Kevin 84
//    uint8_t op_state;
85
    uint8_t i;
260 Kevin 86
 
87
    // Set internal oscillator speed to 32MHz
88
    OSCCONbits.SPLLEN = 1;  // 4x PLL enable (overwritten by config bits)
89
    OSCCONbits.IRCF = 0xE;  // Base frequency @ 8MHz
90
    OSCCONbits.SCS = 0b00;  // System clock determined by config bits
91
 
92
    // Initialize I/O
273 Kevin 93
    IO_Init();
260 Kevin 94
 
273 Kevin 95
    uint8_t last_reset = Get_Last_Reset();
96
    if (last_reset == RESET_POR || last_reset == RESET_BOR ||
97
            last_reset == RESET_MCLR || last_reset == RESET_WDT ||
98
            last_reset == RESET_STK) {
99
        op_state = OP_STATE_IDLE;
100
    }
101
//    if (last_reset == RESET_RST) {
102
//        op_state = OP_STATE_ACTIVE;
103
//    }
104
 
260 Kevin 105
    i2c_slave_addr = Read_Address();
106
 
273 Kevin 107
    // Delay a bit to allow I2C lines to stabilize
275 Kevin 108
    __delay_ms(10);
273 Kevin 109
 
260 Kevin 110
    // Initialize I2C1 in slave mode
111
    I2C1_DATA i2c1_data;
112
    I2C1_Init(&i2c1_data);
113
    I2C1_Configure_Slave(i2c_slave_addr);
114
 
115
    // Initialize I2C2 in master mode
116
    I2C2_DATA i2c2_data;
117
    I2C2_Init(&i2c2_data);
275 Kevin 118
    I2C2_Configure_Master(I2C_1MHZ);
260 Kevin 119
 
120
    // Initialize interrupts
121
    Interrupt_Init();
122
    Interrupt_Enable();
123
 
273 Kevin 124
    MCP23009_Init(&btns);
125
    MCP23009_Query();
126
 
260 Kevin 127
    TLC59116_Init();
273 Kevin 128
//    TLC59116_Write_All(&leds);
260 Kevin 129
 
273 Kevin 130
    if (op_state == OP_STATE_IDLE) {
275 Kevin 131
//        IO_IOC_Enable();
273 Kevin 132
        Idle_Animation();
133
    } else if (op_state == OP_STATE_ACTIVE) {
134
        while (1) {
135
            // Check if an I2C message was received
136
            result = I2C1_Get_Status();
137
            if (result) {
138
                length = I2C1_Read_Buffer(buffer);
139
                if (length == 1 && buffer[0] == CMD_RESET) {
140
                    Reset_Board(OP_STATE_IDLE);
275 Kevin 141
                } else if (length == 1 && buffer[0] == CMD_ACTIVE) {
142
                    Reset_Board(OP_STATE_ACTIVE);
273 Kevin 143
                } else if (length == 17 && buffer[0] == CMD_SET_LEDS) {
144
                    for (i = 0; i < 16; i++) {
275 Kevin 145
                        leds.w[i] = buffer[i + 1];
273 Kevin 146
                    }
147
                    TLC59116_Write_All(&leds);
148
                }
260 Kevin 149
            }
275 Kevin 150
 
151
            I2C2_Master_Restart(MCP23009_ADDR, MCP23009_GPIOA, 1);
152
            do {
153
                result = I2C2_Get_Status();
154
            } while (!result);
155
            length = I2C2_Read_Buffer(buffer);
156
            btns.w = buffer[0];
260 Kevin 157
        }
270 Kevin 158
    }
159
}
260 Kevin 160
 
275 Kevin 161
void Check_I2C(void) {
162
    uint8_t buffer[32];
163
    uint8_t result, length, i;
164
 
165
    // Check if an I2C message was received
166
    result = I2C1_Get_Status();
167
    if (result) {
168
        length = I2C1_Read_Buffer(buffer);
169
        if (length == 1 && buffer[0] == CMD_RESET) {
170
            Reset_Board(OP_STATE_IDLE);
171
        } else if (length == 1 && buffer[0] == CMD_ACTIVE) {
172
            Reset_Board(OP_STATE_ACTIVE);
173
        } else if (length == 17 && buffer[0] == CMD_SET_LEDS) {
174
            for (i = 0; i < 16; i++) {
175
                leds.w[i] = buffer[i + 1];
176
            }
177
            TLC59116_Write_All(&leds);
178
        }
179
    }
180
}
181
 
270 Kevin 182
void Idle_Animation(void) {
183
    LED_VALUES leds = {0};
184
    uint8_t led_direction_bar[8] = {1,0,0,0,0,0,0,0};
185
    uint8_t led_direction_dir[8] = {1,0,0,0};
186
    uint8_t led_direction_ind[8] = {1,0,0,0};
187
    uint8_t led_8_high_thres = 0x80;    // Max brightness of the middle section
188
    uint8_t led_8_next_thresh = 0x40;   // Threshold to start the next LED
189
    uint8_t led_4_high_thres = 0x80;    // Max brightness of the side sections
190
    uint8_t led_4_next_thresh = 0x74;   // Threshold to start the next LED
191
    uint8_t i, next_led;
260 Kevin 192
 
270 Kevin 193
    for (i = 0; i < 16; i++) leds.w[i] = 0x00;
194
 
195
    while (1) {
196
 
275 Kevin 197
        // Check to see if a new message was received
198
        Check_I2C();
199
 
270 Kevin 200
        // Update the LEDs in the middle section
201
        for (i = 0; i < 8; i++) {
202
            // Change the LED brightness depending on its direction
203
            if (led_direction_bar[i] == 1) {
204
                leds.w[i]++;
205
            } else if (led_direction_bar[i] == 2) {
206
                leds.w[i]--;
207
            }
208
 
209
            // Change direction if peak brightness is reached
210
            // When the brightness reaches a middle threshold, start
211
            //   increasing the brightness of the next LED
212
            if (led_direction_bar[i] == 1 && leds.w[i] == led_8_high_thres) {
213
                led_direction_bar[i] = 2;
214
            } else if (led_direction_bar[i] == 1 && leds.w[i] == led_8_next_thresh) {
215
                next_led = (i == 7) ? 0 : i + 1;
216
                led_direction_bar[next_led] = 1;
217
            } else if (led_direction_bar[i] == 2 && leds.w[i] == 0x00) {
218
                led_direction_bar[i] = 0;
219
            }
220
        }
221
 
222
        // Update the LEDs in the right section
223
        for (i = 0; i < 4; i++) {
224
            // Change the LED brightness depending on its direction
225
            if (led_direction_dir[i] == 1) {
226
                leds.w[i+8]++;
227
            } else if (led_direction_dir[i] == 2) {
228
                leds.w[i+8]--;
229
            }
230
 
231
            // Change direction if peak brightness is reached
232
            // When the brightness reaches a middle threshold, start
233
            //   increasing the brightness of the next LED
234
            if (led_direction_dir[i] == 1 && leds.w[i+8] == led_4_high_thres) {
235
                led_direction_dir[i] = 2;
236
            } else if (led_direction_dir[i] == 1 && leds.w[i+8] == led_4_next_thresh) {
237
                next_led = (i == 3) ? 0 : i + 1;
238
                led_direction_dir[next_led] = 1;
239
            } else if (led_direction_dir[i] == 2 && leds.w[i+8] == 0x00) {
240
                led_direction_dir[i] = 0;
241
            }
242
        }
243
 
244
        // Update the LEDs in the left section
245
        for (i = 0; i < 4; i++) {
246
            // Change the LED brightness depending on its direction
247
            if (led_direction_ind[i] == 1) {
248
                leds.w[i+12]++;
249
            } else if (led_direction_ind[i] == 2) {
250
                leds.w[i+12]--;
251
            }
252
 
253
            // Change direction if peak brightness is reached
254
            // When the brightness reaches a middle threshold, start
255
            //   increasing the brightness of the next LED
256
            if (led_direction_ind[i] == 1 && leds.w[i+12] == led_4_high_thres) {
257
                led_direction_ind[i] = 2;
258
            } else if (led_direction_ind[i] == 1 && leds.w[i+12] == led_4_next_thresh) {
259
                next_led = (i == 3) ? 0 : i + 1;
260
                led_direction_ind[next_led] = 1;
261
            } else if (led_direction_ind[i] == 2 && leds.w[i+12] == 0x00) {
262
                led_direction_ind[i] = 0;
263
            }
264
        }
265
 
266
        // Write the LED values to the controller
267
        TLC59116_Write_All(&leds);
268
 
269
        // Delay a bit to slow down the animation
270
        __delay_ms(1);
260 Kevin 271
    }
270 Kevin 272
}