diff options
author | yiancar <yiangosyiangou@cytanet.com.cy> | 2018-05-14 15:17:24 +0100 |
---|---|---|
committer | Jack Humbert <jack.humb@gmail.com> | 2018-05-14 10:17:24 -0400 |
commit | a98a91cf1b923107e9f26df316c1ef2192ff14f7 (patch) | |
tree | 112b22b9ee2f212b4a58e57d2e4b4906d1ef7636 | |
parent | f42ec8aa866386ed0ab8faf7acf9c396aa482519 (diff) | |
download | qmk_firmware-a98a91cf1b923107e9f26df316c1ef2192ff14f7.tar.gz qmk_firmware-a98a91cf1b923107e9f26df316c1ef2192ff14f7.zip |
Rgb matrix fixes, I2C library can now retry if it has failed (#2943)
* Added Modular keyboards L,R and NUM
Created code modules for the 3 modules of the modular keyboard.
Original idea by MechboardsUK. Uses i2c implementation similar to lets
split
* Remove modular from master
This is to fix incorrect branching
* General fixes for RGB_matrix
- Complited speed support for all effects
- Fixed raindrop effects to initialized after toggle
- Fixed raindrop effects to use all available LEDs
- Fixed effect step reverse function
- Moved RGB_MATRIX_SOLID_REACTIVE under correct flag
* Documentation update for RGBmatrix
* More doc updates
* I2C library can now retry if it has failed
- Replaced the original TWIlib by LFKeyboard's modified version
- Allows for an extra argument on TWITransmitData, if blocking is set to 1 function will retry to transmit on failure. Good for noisy boards.
* RGB Matrix, use alternative I2C library
TWIlib seems to be hanging for me sometimes probably due to ISR routine. I have used i2c_master as a good alternative.
Note: this commit is for Wilba6582 to verify before merge
* Update rgb_matrix.c
* RGB matrix cleanup
- Remove TWIlib
-rw-r--r-- | common_features.mk | 2 | ||||
-rw-r--r-- | drivers/avr/TWIlib.c | 232 | ||||
-rw-r--r-- | drivers/avr/TWIlib.h | 82 | ||||
-rwxr-xr-x | drivers/avr/i2c_master.c | 149 | ||||
-rwxr-xr-x | drivers/avr/i2c_master.h | 22 | ||||
-rw-r--r-- | drivers/avr/is31fl3731.c | 36 | ||||
-rw-r--r-- | quantum/rgb_matrix.c | 6 |
7 files changed, 185 insertions, 344 deletions
diff --git a/common_features.mk b/common_features.mk index 7ba7d4815..0778f8e0f 100644 --- a/common_features.mk +++ b/common_features.mk | |||
@@ -117,7 +117,7 @@ endif | |||
117 | ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) | 117 | ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) |
118 | OPT_DEFS += -DRGB_MATRIX_ENABLE | 118 | OPT_DEFS += -DRGB_MATRIX_ENABLE |
119 | SRC += is31fl3731.c | 119 | SRC += is31fl3731.c |
120 | SRC += TWIlib.c | 120 | SRC += i2c_master.c |
121 | SRC += $(QUANTUM_DIR)/color.c | 121 | SRC += $(QUANTUM_DIR)/color.c |
122 | SRC += $(QUANTUM_DIR)/rgb_matrix.c | 122 | SRC += $(QUANTUM_DIR)/rgb_matrix.c |
123 | CIE1931_CURVE = yes | 123 | CIE1931_CURVE = yes |
diff --git a/drivers/avr/TWIlib.c b/drivers/avr/TWIlib.c deleted file mode 100644 index b39e3054a..000000000 --- a/drivers/avr/TWIlib.c +++ /dev/null | |||
@@ -1,232 +0,0 @@ | |||
1 | /* | ||
2 | * TWIlib.c | ||
3 | * | ||
4 | * Created: 6/01/2014 10:41:33 PM | ||
5 | * Author: Chris Herring | ||
6 | * http://www.chrisherring.net/all/tutorial-interrupt-driven-twi-interface-for-avr-part1/ | ||
7 | */ | ||
8 | |||
9 | #include <avr/io.h> | ||
10 | #include <avr/interrupt.h> | ||
11 | #include "TWIlib.h" | ||
12 | #include "util/delay.h" | ||
13 | |||
14 | void TWIInit() | ||
15 | { | ||
16 | TWIInfo.mode = Ready; | ||
17 | TWIInfo.errorCode = 0xFF; | ||
18 | TWIInfo.repStart = 0; | ||
19 | // Set pre-scalers (no pre-scaling) | ||
20 | TWSR = 0; | ||
21 | // Set bit rate | ||
22 | TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; | ||
23 | // Enable TWI and interrupt | ||
24 | TWCR = (1 << TWIE) | (1 << TWEN); | ||
25 | } | ||
26 | |||
27 | uint8_t isTWIReady() | ||
28 | { | ||
29 | if ( (TWIInfo.mode == Ready) | (TWIInfo.mode == RepeatedStartSent) ) | ||
30 | { | ||
31 | return 1; | ||
32 | } | ||
33 | else | ||
34 | { | ||
35 | return 0; | ||
36 | } | ||
37 | } | ||
38 | |||
39 | uint8_t TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart) | ||
40 | { | ||
41 | if (dataLen <= TXMAXBUFLEN) | ||
42 | { | ||
43 | // Wait until ready | ||
44 | while (!isTWIReady()) {_delay_us(1);} | ||
45 | // Set repeated start mode | ||
46 | TWIInfo.repStart = repStart; | ||
47 | // Copy data into the transmit buffer | ||
48 | uint8_t *data = (uint8_t *)TXdata; | ||
49 | for (int i = 0; i < dataLen; i++) | ||
50 | { | ||
51 | TWITransmitBuffer[i] = data[i]; | ||
52 | } | ||
53 | // Copy transmit info to global variables | ||
54 | TXBuffLen = dataLen; | ||
55 | TXBuffIndex = 0; | ||
56 | |||
57 | // If a repeated start has been sent, then devices are already listening for an address | ||
58 | // and another start does not need to be sent. | ||
59 | if (TWIInfo.mode == RepeatedStartSent) | ||
60 | { | ||
61 | TWIInfo.mode = Initializing; | ||
62 | TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer | ||
63 | TWISendTransmit(); // Send the data | ||
64 | } | ||
65 | else // Otherwise, just send the normal start signal to begin transmission. | ||
66 | { | ||
67 | TWIInfo.mode = Initializing; | ||
68 | TWISendStart(); | ||
69 | } | ||
70 | |||
71 | } | ||
72 | else | ||
73 | { | ||
74 | return 1; // return an error if data length is longer than buffer | ||
75 | } | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart) | ||
80 | { | ||
81 | // Check if number of bytes to read can fit in the RXbuffer | ||
82 | if (bytesToRead < RXMAXBUFLEN) | ||
83 | { | ||
84 | // Reset buffer index and set RXBuffLen to the number of bytes to read | ||
85 | RXBuffIndex = 0; | ||
86 | RXBuffLen = bytesToRead; | ||
87 | // Create the one value array for the address to be transmitted | ||
88 | uint8_t TXdata[1]; | ||
89 | // Shift the address and AND a 1 into the read write bit (set to write mode) | ||
90 | TXdata[0] = (TWIaddr << 1) | 0x01; | ||
91 | // Use the TWITransmitData function to initialize the transfer and address the slave | ||
92 | TWITransmitData(TXdata, 1, repStart); | ||
93 | } | ||
94 | else | ||
95 | { | ||
96 | return 0; | ||
97 | } | ||
98 | return 1; | ||
99 | } | ||
100 | |||
101 | ISR (TWI_vect) | ||
102 | { | ||
103 | switch (TWI_STATUS) | ||
104 | { | ||
105 | // ----\/ ---- MASTER TRANSMITTER OR WRITING ADDRESS ----\/ ---- // | ||
106 | case TWI_MT_SLAW_ACK: // SLA+W transmitted and ACK received | ||
107 | // Set mode to Master Transmitter | ||
108 | TWIInfo.mode = MasterTransmitter; | ||
109 | case TWI_START_SENT: // Start condition has been transmitted | ||
110 | case TWI_MT_DATA_ACK: // Data byte has been transmitted, ACK received | ||
111 | if (TXBuffIndex < TXBuffLen) // If there is more data to send | ||
112 | { | ||
113 | TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer | ||
114 | TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||
115 | TWISendTransmit(); // Send the data | ||
116 | } | ||
117 | // This transmission is complete however do not release bus yet | ||
118 | else if (TWIInfo.repStart) | ||
119 | { | ||
120 | TWIInfo.errorCode = 0xFF; | ||
121 | TWISendStart(); | ||
122 | } | ||
123 | // All transmissions are complete, exit | ||
124 | else | ||
125 | { | ||
126 | TWIInfo.mode = Ready; | ||
127 | TWIInfo.errorCode = 0xFF; | ||
128 | TWISendStop(); | ||
129 | } | ||
130 | break; | ||
131 | |||
132 | // ----\/ ---- MASTER RECEIVER ----\/ ---- // | ||
133 | |||
134 | case TWI_MR_SLAR_ACK: // SLA+R has been transmitted, ACK has been received | ||
135 | // Switch to Master Receiver mode | ||
136 | TWIInfo.mode = MasterReceiver; | ||
137 | // If there is more than one byte to be read, receive data byte and return an ACK | ||
138 | if (RXBuffIndex < RXBuffLen-1) | ||
139 | { | ||
140 | TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||
141 | TWISendACK(); | ||
142 | } | ||
143 | // Otherwise when a data byte (the only data byte) is received, return NACK | ||
144 | else | ||
145 | { | ||
146 | TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||
147 | TWISendNACK(); | ||
148 | } | ||
149 | break; | ||
150 | |||
151 | case TWI_MR_DATA_ACK: // Data has been received, ACK has been transmitted. | ||
152 | |||
153 | /// -- HANDLE DATA BYTE --- /// | ||
154 | TWIReceiveBuffer[RXBuffIndex++] = TWDR; | ||
155 | // If there is more than one byte to be read, receive data byte and return an ACK | ||
156 | if (RXBuffIndex < RXBuffLen-1) | ||
157 | { | ||
158 | TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||
159 | TWISendACK(); | ||
160 | } | ||
161 | // Otherwise when a data byte (the only data byte) is received, return NACK | ||
162 | else | ||
163 | { | ||
164 | TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||
165 | TWISendNACK(); | ||
166 | } | ||
167 | break; | ||
168 | |||
169 | case TWI_MR_DATA_NACK: // Data byte has been received, NACK has been transmitted. End of transmission. | ||
170 | |||
171 | /// -- HANDLE DATA BYTE --- /// | ||
172 | TWIReceiveBuffer[RXBuffIndex++] = TWDR; | ||
173 | // This transmission is complete however do not release bus yet | ||
174 | if (TWIInfo.repStart) | ||
175 | { | ||
176 | TWIInfo.errorCode = 0xFF; | ||
177 | TWISendStart(); | ||
178 | } | ||
179 | // All transmissions are complete, exit | ||
180 | else | ||
181 | { | ||
182 | TWIInfo.mode = Ready; | ||
183 | TWIInfo.errorCode = 0xFF; | ||
184 | TWISendStop(); | ||
185 | } | ||
186 | break; | ||
187 | |||
188 | // ----\/ ---- MT and MR common ----\/ ---- // | ||
189 | |||
190 | case TWI_MR_SLAR_NACK: // SLA+R transmitted, NACK received | ||
191 | case TWI_MT_SLAW_NACK: // SLA+W transmitted, NACK received | ||
192 | case TWI_MT_DATA_NACK: // Data byte has been transmitted, NACK received | ||
193 | case TWI_LOST_ARBIT: // Arbitration has been lost | ||
194 | // Return error and send stop and set mode to ready | ||
195 | if (TWIInfo.repStart) | ||
196 | { | ||
197 | TWIInfo.errorCode = TWI_STATUS; | ||
198 | TWISendStart(); | ||
199 | } | ||
200 | // All transmissions are complete, exit | ||
201 | else | ||
202 | { | ||
203 | TWIInfo.mode = Ready; | ||
204 | TWIInfo.errorCode = TWI_STATUS; | ||
205 | TWISendStop(); | ||
206 | } | ||
207 | break; | ||
208 | case TWI_REP_START_SENT: // Repeated start has been transmitted | ||
209 | // Set the mode but DO NOT clear TWINT as the next data is not yet ready | ||
210 | TWIInfo.mode = RepeatedStartSent; | ||
211 | break; | ||
212 | |||
213 | // ----\/ ---- SLAVE RECEIVER ----\/ ---- // | ||
214 | |||
215 | // TODO IMPLEMENT SLAVE RECEIVER FUNCTIONALITY | ||
216 | |||
217 | // ----\/ ---- SLAVE TRANSMITTER ----\/ ---- // | ||
218 | |||
219 | // TODO IMPLEMENT SLAVE TRANSMITTER FUNCTIONALITY | ||
220 | |||
221 | // ----\/ ---- MISCELLANEOUS STATES ----\/ ---- // | ||
222 | case TWI_NO_RELEVANT_INFO: // It is not really possible to get into this ISR on this condition | ||
223 | // Rather, it is there to be manually set between operations | ||
224 | break; | ||
225 | case TWI_ILLEGAL_START_STOP: // Illegal START/STOP, abort and return error | ||
226 | TWIInfo.errorCode = TWI_ILLEGAL_START_STOP; | ||
227 | TWIInfo.mode = Ready; | ||
228 | TWISendStop(); | ||
229 | break; | ||
230 | } | ||
231 | |||
232 | } | ||
diff --git a/drivers/avr/TWIlib.h b/drivers/avr/TWIlib.h deleted file mode 100644 index 23fd1f09a..000000000 --- a/drivers/avr/TWIlib.h +++ /dev/null | |||
@@ -1,82 +0,0 @@ | |||
1 | /* | ||
2 | * TWIlib.h | ||
3 | * | ||
4 | * Created: 6/01/2014 10:38:42 PM | ||
5 | * Author: Chris Herring | ||
6 | * http://www.chrisherring.net/all/tutorial-interrupt-driven-twi-interface-for-avr-part1/ | ||
7 | */ | ||
8 | |||
9 | |||
10 | #ifndef TWILIB_H_ | ||
11 | #define TWILIB_H_ | ||
12 | // TWI bit rate (was 100000) | ||
13 | #define TWI_FREQ 400000 | ||
14 | // Get TWI status | ||
15 | #define TWI_STATUS (TWSR & 0xF8) | ||
16 | // Transmit buffer length | ||
17 | #define TXMAXBUFLEN 20 | ||
18 | // Receive buffer length | ||
19 | #define RXMAXBUFLEN 20 | ||
20 | // Global transmit buffer | ||
21 | uint8_t TWITransmitBuffer[TXMAXBUFLEN]; | ||
22 | // Global receive buffer | ||
23 | volatile uint8_t TWIReceiveBuffer[RXMAXBUFLEN]; | ||
24 | // Buffer indexes | ||
25 | volatile int TXBuffIndex; // Index of the transmit buffer. Is volatile, can change at any time. | ||
26 | int RXBuffIndex; // Current index in the receive buffer | ||
27 | // Buffer lengths | ||
28 | int TXBuffLen; // The total length of the transmit buffer | ||
29 | int RXBuffLen; // The total number of bytes to read (should be less than RXMAXBUFFLEN) | ||
30 | |||
31 | typedef enum { | ||
32 | Ready, | ||
33 | Initializing, | ||
34 | RepeatedStartSent, | ||
35 | MasterTransmitter, | ||
36 | MasterReceiver, | ||
37 | SlaceTransmitter, | ||
38 | SlaveReciever | ||
39 | } TWIMode; | ||
40 | |||
41 | typedef struct TWIInfoStruct{ | ||
42 | TWIMode mode; | ||
43 | uint8_t errorCode; | ||
44 | uint8_t repStart; | ||
45 | }TWIInfoStruct; | ||
46 | TWIInfoStruct TWIInfo; | ||
47 | |||
48 | |||
49 | // TWI Status Codes | ||
50 | #define TWI_START_SENT 0x08 // Start sent | ||
51 | #define TWI_REP_START_SENT 0x10 // Repeated Start sent | ||
52 | // Master Transmitter Mode | ||
53 | #define TWI_MT_SLAW_ACK 0x18 // SLA+W sent and ACK received | ||
54 | #define TWI_MT_SLAW_NACK 0x20 // SLA+W sent and NACK received | ||
55 | #define TWI_MT_DATA_ACK 0x28 // DATA sent and ACK received | ||
56 | #define TWI_MT_DATA_NACK 0x30 // DATA sent and NACK received | ||
57 | // Master Receiver Mode | ||
58 | #define TWI_MR_SLAR_ACK 0x40 // SLA+R sent, ACK received | ||
59 | #define TWI_MR_SLAR_NACK 0x48 // SLA+R sent, NACK received | ||
60 | #define TWI_MR_DATA_ACK 0x50 // Data received, ACK returned | ||
61 | #define TWI_MR_DATA_NACK 0x58 // Data received, NACK returned | ||
62 | |||
63 | // Miscellaneous States | ||
64 | #define TWI_LOST_ARBIT 0x38 // Arbitration has been lost | ||
65 | #define TWI_NO_RELEVANT_INFO 0xF8 // No relevant information available | ||
66 | #define TWI_ILLEGAL_START_STOP 0x00 // Illegal START or STOP condition has been detected | ||
67 | #define TWI_SUCCESS 0xFF // Successful transfer, this state is impossible from TWSR as bit2 is 0 and read only | ||
68 | |||
69 | |||
70 | #define TWISendStart() (TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN)|(1<<TWIE)) // Send the START signal, enable interrupts and TWI, clear TWINT flag to resume transfer. | ||
71 | #define TWISendStop() (TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)) // Send the STOP signal, enable interrupts and TWI, clear TWINT flag. | ||
72 | #define TWISendTransmit() (TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)) // Used to resume a transfer, clear TWINT and ensure that TWI and interrupts are enabled. | ||
73 | #define TWISendACK() (TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)|(1<<TWEA)) // FOR MR mode. Resume a transfer, ensure that TWI and interrupts are enabled and respond with an ACK if the device is addressed as a slave or after it receives a byte. | ||
74 | #define TWISendNACK() (TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)) // FOR MR mode. Resume a transfer, ensure that TWI and interrupts are enabled but DO NOT respond with an ACK if the device is addressed as a slave or after it receives a byte. | ||
75 | |||
76 | // Function declarations | ||
77 | uint8_t TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart); | ||
78 | void TWIInit(void); | ||
79 | uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart); | ||
80 | uint8_t isTWIReady(void); | ||
81 | |||
82 | #endif // TWICOMMS_H_ \ No newline at end of file | ||
diff --git a/drivers/avr/i2c_master.c b/drivers/avr/i2c_master.c new file mode 100755 index 000000000..f4a4bb7b0 --- /dev/null +++ b/drivers/avr/i2c_master.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* Library made by: g4lvanix | ||
2 | * Github repository: https://github.com/g4lvanix/I2C-master-lib | ||
3 | */ | ||
4 | |||
5 | #include <avr/io.h> | ||
6 | #include <util/twi.h> | ||
7 | |||
8 | #include "i2c_master.h" | ||
9 | |||
10 | #define F_SCL 400000UL // SCL frequency | ||
11 | #define Prescaler 1 | ||
12 | #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2) | ||
13 | |||
14 | void i2c_init(void) | ||
15 | { | ||
16 | TWBR = (uint8_t)TWBR_val; | ||
17 | } | ||
18 | |||
19 | uint8_t i2c_start(uint8_t address) | ||
20 | { | ||
21 | // reset TWI control register | ||
22 | TWCR = 0; | ||
23 | // transmit START condition | ||
24 | TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | ||
25 | // wait for end of transmission | ||
26 | while( !(TWCR & (1<<TWINT)) ); | ||
27 | |||
28 | // check if the start condition was successfully transmitted | ||
29 | if((TWSR & 0xF8) != TW_START){ return 1; } | ||
30 | |||
31 | // load slave address into data register | ||
32 | TWDR = address; | ||
33 | // start transmission of address | ||
34 | TWCR = (1<<TWINT) | (1<<TWEN); | ||
35 | // wait for end of transmission | ||
36 | while( !(TWCR & (1<<TWINT)) ); | ||
37 | |||
38 | // check if the device has acknowledged the READ / WRITE mode | ||
39 | uint8_t twst = TW_STATUS & 0xF8; | ||
40 | if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1; | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | uint8_t i2c_write(uint8_t data) | ||
46 | { | ||
47 | // load data into data register | ||
48 | TWDR = data; | ||
49 | // start transmission of data | ||
50 | TWCR = (1<<TWINT) | (1<<TWEN); | ||
51 | // wait for end of transmission | ||
52 | while( !(TWCR & (1<<TWINT)) ); | ||
53 | |||
54 | if( (TWSR & 0xF8) != TW_MT_DATA_ACK ){ return 1; } | ||
55 | |||
56 | return 0; | ||
57 | } | ||
58 | |||
59 | uint8_t i2c_read_ack(void) | ||
60 | { | ||
61 | |||
62 | // start TWI module and acknowledge data after reception | ||
63 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA); | ||
64 | // wait for end of transmission | ||
65 | while( !(TWCR & (1<<TWINT)) ); | ||
66 | // return received data from TWDR | ||
67 | return TWDR; | ||
68 | } | ||
69 | |||
70 | uint8_t i2c_read_nack(void) | ||
71 | { | ||
72 | |||
73 | // start receiving without acknowledging reception | ||
74 | TWCR = (1<<TWINT) | (1<<TWEN); | ||
75 | // wait for end of transmission | ||
76 | while( !(TWCR & (1<<TWINT)) ); | ||
77 | // return received data from TWDR | ||
78 | return TWDR; | ||
79 | } | ||
80 | |||
81 | uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length) | ||
82 | { | ||
83 | if (i2c_start(address | I2C_WRITE)) return 1; | ||
84 | |||
85 | for (uint16_t i = 0; i < length; i++) | ||
86 | { | ||
87 | if (i2c_write(data[i])) return 1; | ||
88 | } | ||
89 | |||
90 | i2c_stop(); | ||
91 | |||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length) | ||
96 | { | ||
97 | if (i2c_start(address | I2C_READ)) return 1; | ||
98 | |||
99 | for (uint16_t i = 0; i < (length-1); i++) | ||
100 | { | ||
101 | data[i] = i2c_read_ack(); | ||
102 | } | ||
103 | data[(length-1)] = i2c_read_nack(); | ||
104 | |||
105 | i2c_stop(); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length) | ||
111 | { | ||
112 | if (i2c_start(devaddr | 0x00)) return 1; | ||
113 | |||
114 | i2c_write(regaddr); | ||
115 | |||
116 | for (uint16_t i = 0; i < length; i++) | ||
117 | { | ||
118 | if (i2c_write(data[i])) return 1; | ||
119 | } | ||
120 | |||
121 | i2c_stop(); | ||
122 | |||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length) | ||
127 | { | ||
128 | if (i2c_start(devaddr)) return 1; | ||
129 | |||
130 | i2c_write(regaddr); | ||
131 | |||
132 | if (i2c_start(devaddr | 0x01)) return 1; | ||
133 | |||
134 | for (uint16_t i = 0; i < (length-1); i++) | ||
135 | { | ||
136 | data[i] = i2c_read_ack(); | ||
137 | } | ||
138 | data[(length-1)] = i2c_read_nack(); | ||
139 | |||
140 | i2c_stop(); | ||
141 | |||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | void i2c_stop(void) | ||
146 | { | ||
147 | // transmit STOP condition | ||
148 | TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | ||
149 | } | ||
diff --git a/drivers/avr/i2c_master.h b/drivers/avr/i2c_master.h new file mode 100755 index 000000000..2479d28d5 --- /dev/null +++ b/drivers/avr/i2c_master.h | |||
@@ -0,0 +1,22 @@ | |||
1 | /* Library made by: g4lvanix | ||
2 | * Github repository: https://github.com/g4lvanix/I2C-master-lib | ||
3 | */ | ||
4 | |||
5 | #ifndef I2C_MASTER_H | ||
6 | #define I2C_MASTER_H | ||
7 | |||
8 | #define I2C_READ 0x01 | ||
9 | #define I2C_WRITE 0x00 | ||
10 | |||
11 | void i2c_init(void); | ||
12 | uint8_t i2c_start(uint8_t address); | ||
13 | uint8_t i2c_write(uint8_t data); | ||
14 | uint8_t i2c_read_ack(void); | ||
15 | uint8_t i2c_read_nack(void); | ||
16 | uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length); | ||
17 | uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length); | ||
18 | uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); | ||
19 | uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); | ||
20 | void i2c_stop(void); | ||
21 | |||
22 | #endif // I2C_MASTER_H | ||
diff --git a/drivers/avr/is31fl3731.c b/drivers/avr/is31fl3731.c index e5941cf41..c7a99e3a3 100644 --- a/drivers/avr/is31fl3731.c +++ b/drivers/avr/is31fl3731.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <avr/io.h> | 20 | #include <avr/io.h> |
21 | #include <util/delay.h> | 21 | #include <util/delay.h> |
22 | #include <string.h> | 22 | #include <string.h> |
23 | #include "TWIlib.h" | 23 | #include "i2c_master.h" |
24 | #include "progmem.h" | 24 | #include "progmem.h" |
25 | 25 | ||
26 | // This is a 7-bit address, that gets left-shifted and bit 0 | 26 | // This is a 7-bit address, that gets left-shifted and bit 0 |
@@ -50,7 +50,7 @@ | |||
50 | #define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine' | 50 | #define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine' |
51 | 51 | ||
52 | // Transfer buffer for TWITransmitData() | 52 | // Transfer buffer for TWITransmitData() |
53 | uint8_t g_twi_transfer_buffer[TXMAXBUFLEN]; | 53 | uint8_t g_twi_transfer_buffer[20]; |
54 | 54 | ||
55 | // These buffers match the IS31FL3731 PWM registers 0x24-0xB3. | 55 | // These buffers match the IS31FL3731 PWM registers 0x24-0xB3. |
56 | // Storing them like this is optimal for I2C transfers to the registers. | 56 | // Storing them like this is optimal for I2C transfers to the registers. |
@@ -80,17 +80,11 @@ bool g_led_control_registers_update_required = false; | |||
80 | 80 | ||
81 | void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ) | 81 | void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ) |
82 | { | 82 | { |
83 | g_twi_transfer_buffer[0] = (addr << 1) | 0x00; | 83 | g_twi_transfer_buffer[0] = reg; |
84 | g_twi_transfer_buffer[1] = reg; | 84 | g_twi_transfer_buffer[1] = data; |
85 | g_twi_transfer_buffer[2] = data; | 85 | |
86 | 86 | //Transmit data until succesful | |
87 | // Set the error code to have no relevant information | 87 | while(i2c_transmit(addr << 1, g_twi_transfer_buffer,2) != 0); |
88 | TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||
89 | // Continuously attempt to transmit data until a successful transmission occurs | ||
90 | //while ( TWIInfo.errorCode != 0xFF ) | ||
91 | //{ | ||
92 | TWITransmitData( g_twi_transfer_buffer, 3, 0 ); | ||
93 | //} | ||
94 | } | 88 | } |
95 | 89 | ||
96 | void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) | 90 | void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) |
@@ -100,29 +94,21 @@ void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) | |||
100 | // transmit PWM registers in 9 transfers of 16 bytes | 94 | // transmit PWM registers in 9 transfers of 16 bytes |
101 | // g_twi_transfer_buffer[] is 20 bytes | 95 | // g_twi_transfer_buffer[] is 20 bytes |
102 | 96 | ||
103 | // set the I2C address | ||
104 | g_twi_transfer_buffer[0] = (addr << 1) | 0x00; | ||
105 | |||
106 | // iterate over the pwm_buffer contents at 16 byte intervals | 97 | // iterate over the pwm_buffer contents at 16 byte intervals |
107 | for ( int i = 0; i < 144; i += 16 ) | 98 | for ( int i = 0; i < 144; i += 16 ) |
108 | { | 99 | { |
109 | // set the first register, e.g. 0x24, 0x34, 0x44, etc. | 100 | // set the first register, e.g. 0x24, 0x34, 0x44, etc. |
110 | g_twi_transfer_buffer[1] = 0x24 + i; | 101 | g_twi_transfer_buffer[0] = 0x24 + i; |
111 | // copy the data from i to i+15 | 102 | // copy the data from i to i+15 |
112 | // device will auto-increment register for data after the first byte | 103 | // device will auto-increment register for data after the first byte |
113 | // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer | 104 | // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer |
114 | for ( int j = 0; j < 16; j++ ) | 105 | for ( int j = 0; j < 16; j++ ) |
115 | { | 106 | { |
116 | g_twi_transfer_buffer[2 + j] = pwm_buffer[i + j]; | 107 | g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; |
117 | } | 108 | } |
118 | 109 | ||
119 | // Set the error code to have no relevant information | 110 | //Transmit buffer until succesful |
120 | TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | 111 | while(i2c_transmit(addr << 1, g_twi_transfer_buffer,17) != 0); |
121 | // Continuously attempt to transmit data until a successful transmission occurs | ||
122 | while ( TWIInfo.errorCode != 0xFF ) | ||
123 | { | ||
124 | TWITransmitData( g_twi_transfer_buffer, 16 + 2, 0 ); | ||
125 | } | ||
126 | } | 112 | } |
127 | } | 113 | } |
128 | 114 | ||
diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index f3d012bc3..992ce99de 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | #include "rgb_matrix.h" | 19 | #include "rgb_matrix.h" |
20 | #include <avr/io.h> | 20 | #include <avr/io.h> |
21 | #include "TWIlib.h" | 21 | #include "i2c_master.h" |
22 | #include <util/delay.h> | 22 | #include <util/delay.h> |
23 | #include <avr/interrupt.h> | 23 | #include <avr/interrupt.h> |
24 | #include "progmem.h" | 24 | #include "progmem.h" |
@@ -722,10 +722,8 @@ void rgb_matrix_indicators_user(void) {} | |||
722 | // } | 722 | // } |
723 | 723 | ||
724 | void rgb_matrix_init_drivers(void) { | 724 | void rgb_matrix_init_drivers(void) { |
725 | //sei(); | ||
726 | |||
727 | // Initialize TWI | 725 | // Initialize TWI |
728 | TWIInit(); | 726 | i2c_init(); |
729 | IS31FL3731_init( DRIVER_ADDR_1 ); | 727 | IS31FL3731_init( DRIVER_ADDR_1 ); |
730 | IS31FL3731_init( DRIVER_ADDR_2 ); | 728 | IS31FL3731_init( DRIVER_ADDR_2 ); |
731 | 729 | ||