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 | ||
