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;
78
 
260 Kevin 79
int main(void) {
80
    uint8_t buffer[32];
81
    uint8_t result, length;
82
    uint8_t i2c_slave_addr;
273 Kevin 83
//    uint8_t op_state;
84
    uint8_t i;
260 Kevin 85
 
86
    // Set internal oscillator speed to 32MHz
87
    OSCCONbits.SPLLEN = 1;  // 4x PLL enable (overwritten by config bits)
88
    OSCCONbits.IRCF = 0xE;  // Base frequency @ 8MHz
89
    OSCCONbits.SCS = 0b00;  // System clock determined by config bits
90
 
91
    // Initialize I/O
273 Kevin 92
    IO_Init();
260 Kevin 93
 
273 Kevin 94
    uint8_t last_reset = Get_Last_Reset();
95
    if (last_reset == RESET_POR || last_reset == RESET_BOR ||
96
            last_reset == RESET_MCLR || last_reset == RESET_WDT ||
97
            last_reset == RESET_STK) {
98
        op_state = OP_STATE_IDLE;
99
    }
100
//    if (last_reset == RESET_RST) {
101
//        op_state = OP_STATE_ACTIVE;
102
//    }
103
 
260 Kevin 104
    i2c_slave_addr = Read_Address();
105
 
273 Kevin 106
    // Delay a bit to allow I2C lines to stabilize
107
    __delay_ms(1);
108
 
260 Kevin 109
    // Initialize I2C1 in slave mode
110
    I2C1_DATA i2c1_data;
111
    I2C1_Init(&i2c1_data);
112
    I2C1_Configure_Slave(i2c_slave_addr);
113
 
114
    // Initialize I2C2 in master mode
115
    I2C2_DATA i2c2_data;
116
    I2C2_Init(&i2c2_data);
117
    I2C2_Configure_Master(I2C_400KHZ);
118
 
119
    // Initialize interrupts
120
    Interrupt_Init();
121
    Interrupt_Enable();
122
 
273 Kevin 123
    MCP23009_Init(&btns);
124
    MCP23009_Query();
125
 
126
    LED_VALUES leds = {0x00};
260 Kevin 127
    TLC59116_Init();
273 Kevin 128
//    TLC59116_Write_All(&leds);
260 Kevin 129
 
273 Kevin 130
    if (op_state == OP_STATE_IDLE) {
131
        IO_IOC_Enable();
132
        Idle_Animation();
133
    } else if (op_state == OP_STATE_ACTIVE) {
134
        while (1) {
135
            __delay_ms(1);
136
            // Read value of buttons
137
            MCP23009_Query();
260 Kevin 138
 
273 Kevin 139
            // Check if an I2C message was received
140
            result = I2C1_Get_Status();
141
            if (result) {
142
                length = I2C1_Read_Buffer(buffer);
143
                if (length == 1 && buffer[0] == CMD_RESET) {
144
                    Reset_Board(OP_STATE_IDLE);
145
                } else if (length == 17 && buffer[0] == CMD_SET_LEDS) {
146
                    for (i = 0; i < 16; i++) {
147
                        leds.w[i] = buffer[i+1];
148
                    }
149
                    TLC59116_Write_All(&leds);
150
                }
260 Kevin 151
            }
152
        }
270 Kevin 153
    }
154
}
260 Kevin 155
 
270 Kevin 156
void Idle_Animation(void) {
157
    LED_VALUES leds = {0};
158
    uint8_t led_direction_bar[8] = {1,0,0,0,0,0,0,0};
159
    uint8_t led_direction_dir[8] = {1,0,0,0};
160
    uint8_t led_direction_ind[8] = {1,0,0,0};
161
    uint8_t led_8_high_thres = 0x80;    // Max brightness of the middle section
162
    uint8_t led_8_next_thresh = 0x40;   // Threshold to start the next LED
163
    uint8_t led_4_high_thres = 0x80;    // Max brightness of the side sections
164
    uint8_t led_4_next_thresh = 0x74;   // Threshold to start the next LED
165
    uint8_t i, next_led;
260 Kevin 166
 
270 Kevin 167
    for (i = 0; i < 16; i++) leds.w[i] = 0x00;
168
 
169
    while (1) {
170
 
171
        // Update the LEDs in the middle section
172
        for (i = 0; i < 8; i++) {
173
            // Change the LED brightness depending on its direction
174
            if (led_direction_bar[i] == 1) {
175
                leds.w[i]++;
176
            } else if (led_direction_bar[i] == 2) {
177
                leds.w[i]--;
178
            }
179
 
180
            // Change direction if peak brightness is reached
181
            // When the brightness reaches a middle threshold, start
182
            //   increasing the brightness of the next LED
183
            if (led_direction_bar[i] == 1 && leds.w[i] == led_8_high_thres) {
184
                led_direction_bar[i] = 2;
185
            } else if (led_direction_bar[i] == 1 && leds.w[i] == led_8_next_thresh) {
186
                next_led = (i == 7) ? 0 : i + 1;
187
                led_direction_bar[next_led] = 1;
188
            } else if (led_direction_bar[i] == 2 && leds.w[i] == 0x00) {
189
                led_direction_bar[i] = 0;
190
            }
191
        }
192
 
193
        // Update the LEDs in the right section
194
        for (i = 0; i < 4; i++) {
195
            // Change the LED brightness depending on its direction
196
            if (led_direction_dir[i] == 1) {
197
                leds.w[i+8]++;
198
            } else if (led_direction_dir[i] == 2) {
199
                leds.w[i+8]--;
200
            }
201
 
202
            // Change direction if peak brightness is reached
203
            // When the brightness reaches a middle threshold, start
204
            //   increasing the brightness of the next LED
205
            if (led_direction_dir[i] == 1 && leds.w[i+8] == led_4_high_thres) {
206
                led_direction_dir[i] = 2;
207
            } else if (led_direction_dir[i] == 1 && leds.w[i+8] == led_4_next_thresh) {
208
                next_led = (i == 3) ? 0 : i + 1;
209
                led_direction_dir[next_led] = 1;
210
            } else if (led_direction_dir[i] == 2 && leds.w[i+8] == 0x00) {
211
                led_direction_dir[i] = 0;
212
            }
213
        }
214
 
215
        // Update the LEDs in the left section
216
        for (i = 0; i < 4; i++) {
217
            // Change the LED brightness depending on its direction
218
            if (led_direction_ind[i] == 1) {
219
                leds.w[i+12]++;
220
            } else if (led_direction_ind[i] == 2) {
221
                leds.w[i+12]--;
222
            }
223
 
224
            // Change direction if peak brightness is reached
225
            // When the brightness reaches a middle threshold, start
226
            //   increasing the brightness of the next LED
227
            if (led_direction_ind[i] == 1 && leds.w[i+12] == led_4_high_thres) {
228
                led_direction_ind[i] = 2;
229
            } else if (led_direction_ind[i] == 1 && leds.w[i+12] == led_4_next_thresh) {
230
                next_led = (i == 3) ? 0 : i + 1;
231
                led_direction_ind[next_led] = 1;
232
            } else if (led_direction_ind[i] == 2 && leds.w[i+12] == 0x00) {
233
                led_direction_ind[i] = 0;
234
            }
235
        }
236
 
237
        // Write the LED values to the controller
238
        TLC59116_Write_All(&leds);
239
 
240
        // Delay a bit to slow down the animation
241
        __delay_ms(1);
260 Kevin 242
    }
243
 
270 Kevin 244
}