1 | #include <avr/io.h>
|
2 | #include <util/delay.h>
|
3 | #include <compat/twi.h>
|
4 | #include <avr/interrupt.h>
|
5 | #include "l74hc4051.h"
|
6 | #include "adc.h"
|
7 |
|
8 | #define I2C_ADDR 0x4E
|
9 |
|
10 | #deinfe OP_RESET 0x00
|
11 | #define OP_PROBE 0x01
|
12 | #define OP_SINGLE 0x02
|
13 |
|
14 | #define IODIR 0x00
|
15 | #define GPIO 0x09
|
16 | #define OLAT 0x0A
|
17 | unsigned char regaddr; // Store the MCP23008 Requested Register Address
|
18 | unsigned char regdata; // Store the MCP23008 Register Address Data
|
19 | unsigned char index;
|
20 |
|
21 | uint16_t current_values[40] = {0};
|
22 | uint16_t old_values[40] = {0};
|
23 |
|
24 | void i2c_slave_action(unsigned char rw_status)
|
25 | {
|
26 | // rw_status: 0-Read, 1-Write
|
27 | switch(regaddr) {
|
28 |
|
29 | case OP_RESET:
|
30 | if(rw_status)++
|
31 | {
|
32 | index = 0;
|
33 | }
|
34 | else
|
35 | {
|
36 | index = 0;
|
37 | regdata = 0xFF;
|
38 | }
|
39 | break;
|
40 |
|
41 |
|
42 | case OP_PROBE:
|
43 | if (rw_status) {
|
44 | } else {
|
45 | if(index < 80)
|
46 | {
|
47 | regdata=current_values[index++];
|
48 | }
|
49 | else
|
50 | {
|
51 | index = 0;
|
52 | regdata=0x00;
|
53 | }
|
54 | }
|
55 | break;
|
56 | }
|
57 | }
|
58 | ISR(TWI_vect)
|
59 | {
|
60 | static unsigned char i2c_state;
|
61 | unsigned char twi_status;
|
62 | // Disable Global Interrupt
|
63 | cli();
|
64 | // Get TWI Status Register, mask the prescaler bits (TWPS1,TWPS0)
|
65 | twi_status=TWSR & 0xF8;
|
66 |
|
67 | switch(twi_status) {
|
68 | case TW_SR_SLA_ACK: // 0x60: SLA+W received, ACK returned
|
69 | i2c_state=0; // Start I2C State for Register Address required
|
70 |
|
71 | TWCR |= (1<<TWINT); // Clear TWINT Flag
|
72 | break;
|
73 | case TW_SR_DATA_ACK: // 0x80: data received, ACK returned
|
74 | if (i2c_state == 0) {
|
75 | regaddr = TWDR; // Save data to the register address
|
76 | i2c_state = 1;
|
77 | } else {
|
78 | regdata = TWDR; // Save to the register data
|
79 | i2c_state = 2;
|
80 | }
|
81 |
|
82 | TWCR |= (1<<TWINT); // Clear TWINT Flag
|
83 | break;
|
84 | case TW_SR_STOP: // 0xA0: stop or repeated start condition received while selected
|
85 | if (i2c_state == 2) {
|
86 | i2c_slave_action(1); // Call Write I2C Action (rw_status = 1)
|
87 | i2c_state = 0; // Reset I2C State
|
88 | }
|
89 |
|
90 | TWCR |= (1<<TWINT); // Clear TWINT Flag
|
91 | break;
|
92 |
|
93 | case TW_ST_SLA_ACK: // 0xA8: SLA+R received, ACK returned
|
94 | case TW_ST_DATA_ACK: // 0xB8: data transmitted, ACK received
|
95 | if (i2c_state == 1) {
|
96 | i2c_slave_action(0); // Call Read I2C Action (rw_status = 0)
|
97 | TWDR = regdata; // Store data in TWDR register
|
98 | i2c_state = 0; // Reset I2C State
|
99 | }
|
100 |
|
101 | TWCR |= (1<<TWINT); // Clear TWINT Flag
|
102 | break;
|
103 | case TW_ST_DATA_NACK: // 0xC0: data transmitted, NACK received
|
104 | case TW_ST_LAST_DATA: // 0xC8: last data byte transmitted, ACK received
|
105 | case TW_BUS_ERROR: // 0x00: illegal start or stop condition
|
106 | default:
|
107 | TWCR |= (1<<TWINT); // Clear TWINT Flag
|
108 | i2c_state = 0; // Back to the Begining State
|
109 | }
|
110 | // Enable Global Interrupt
|
111 | sei();
|
112 | }
|
113 | int main(void)
|
114 | {
|
115 | DDRB = 0xFE; // Set PORTB: PB0=Input, Others as Output
|
116 | PORTB = 0x00;
|
117 | DDRD = 0xFF; // Set PORTD to Output
|
118 | PORTD = 0x00; // Set All PORTD to Low
|
119 |
|
120 |
|
121 | // XXX
|
122 | l74hc4051_init();
|
123 | adc_setchannel(1);
|
124 | adc_init();
|
125 |
|
126 | // Initial I2C Slave
|
127 | TWAR = I2C_ADDR & 0xFE; // Set I2C Address, Ignore I2C General Address 0x00
|
128 | TWDR = 0x00; // Default Initial Value
|
129 | // Start Slave Listening: Clear TWINT Flag, Enable ACK, Enable TWI, TWI Interrupt Enable
|
130 | TWCR = (1<<TWINT) | (1<<TWEA) | (1<<TWEN) | (1<<TWIE);
|
131 | // Enable Global Interrupt
|
132 | sei();
|
133 |
|
134 | // Initial Variable Used
|
135 | regaddr=0;
|
136 | regdata=0;
|
137 |
|
138 | for(;;) {
|
139 | uint8_t i,j = 0;
|
140 | for(j=0; j < 5; j++)
|
141 | {
|
142 | for(i=0; i<L74HC4051_MAXCH; i++) {
|
143 | l74hc4051_setchannel(i);
|
144 | current_values[i*j] = adc_read(j);
|
145 | }
|
146 | _delay_us(100);
|
147 | }
|
148 |
|
149 | }
|
150 | return 0;
|
151 | }
|