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
This commit is contained in:
		| @@ -117,7 +117,7 @@ endif | ||||
| ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) | ||||
|     OPT_DEFS += -DRGB_MATRIX_ENABLE | ||||
|     SRC += is31fl3731.c | ||||
|     SRC += TWIlib.c | ||||
|     SRC += i2c_master.c | ||||
|     SRC += $(QUANTUM_DIR)/color.c | ||||
|     SRC += $(QUANTUM_DIR)/rgb_matrix.c | ||||
|     CIE1931_CURVE = yes | ||||
|   | ||||
| @@ -1,232 +0,0 @@ | ||||
| /* | ||||
|  * TWIlib.c | ||||
|  * | ||||
|  *  Created: 6/01/2014 10:41:33 PM | ||||
|  *  Author: Chris Herring | ||||
|  *  http://www.chrisherring.net/all/tutorial-interrupt-driven-twi-interface-for-avr-part1/ | ||||
|  */  | ||||
|  | ||||
| #include <avr/io.h> | ||||
| #include <avr/interrupt.h> | ||||
| #include "TWIlib.h" | ||||
| #include "util/delay.h" | ||||
|  | ||||
| void TWIInit() | ||||
| { | ||||
| 	TWIInfo.mode = Ready; | ||||
| 	TWIInfo.errorCode = 0xFF; | ||||
| 	TWIInfo.repStart = 0; | ||||
| 	// Set pre-scalers (no pre-scaling) | ||||
| 	TWSR = 0; | ||||
| 	// Set bit rate | ||||
| 	TWBR = ((F_CPU / TWI_FREQ) - 16) / 2; | ||||
| 	// Enable TWI and interrupt | ||||
| 	TWCR = (1 << TWIE) | (1 << TWEN); | ||||
| } | ||||
|  | ||||
| uint8_t isTWIReady() | ||||
| { | ||||
| 	if ( (TWIInfo.mode == Ready) | (TWIInfo.mode == RepeatedStartSent) ) | ||||
| 	{ | ||||
| 		return 1; | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| uint8_t TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart) | ||||
| { | ||||
| 	if (dataLen <= TXMAXBUFLEN) | ||||
| 	{ | ||||
| 		// Wait until ready | ||||
| 		while (!isTWIReady()) {_delay_us(1);} | ||||
| 		// Set repeated start mode | ||||
| 		TWIInfo.repStart = repStart; | ||||
| 		// Copy data into the transmit buffer | ||||
| 		uint8_t *data = (uint8_t *)TXdata; | ||||
| 		for (int i = 0; i < dataLen; i++) | ||||
| 		{ | ||||
| 			TWITransmitBuffer[i] = data[i]; | ||||
| 		} | ||||
| 		// Copy transmit info to global variables | ||||
| 		TXBuffLen = dataLen; | ||||
| 		TXBuffIndex = 0; | ||||
| 		 | ||||
| 		// If a repeated start has been sent, then devices are already listening for an address | ||||
| 		// and another start does not need to be sent.  | ||||
| 		if (TWIInfo.mode == RepeatedStartSent) | ||||
| 		{ | ||||
| 			TWIInfo.mode = Initializing; | ||||
| 			TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer | ||||
| 			TWISendTransmit(); // Send the data | ||||
| 		} | ||||
| 		else // Otherwise, just send the normal start signal to begin transmission. | ||||
| 		{ | ||||
| 			TWIInfo.mode = Initializing; | ||||
| 			TWISendStart(); | ||||
| 		} | ||||
| 		 | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return 1; // return an error if data length is longer than buffer | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart) | ||||
| { | ||||
| 	// Check if number of bytes to read can fit in the RXbuffer | ||||
| 	if (bytesToRead < RXMAXBUFLEN) | ||||
| 	{ | ||||
| 		// Reset buffer index and set RXBuffLen to the number of bytes to read | ||||
| 		RXBuffIndex = 0; | ||||
| 		RXBuffLen = bytesToRead; | ||||
| 		// Create the one value array for the address to be transmitted | ||||
| 		uint8_t TXdata[1]; | ||||
| 		// Shift the address and AND a 1 into the read write bit (set to write mode) | ||||
| 		TXdata[0] = (TWIaddr << 1) | 0x01; | ||||
| 		// Use the TWITransmitData function to initialize the transfer and address the slave | ||||
| 		TWITransmitData(TXdata, 1, repStart); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 1; | ||||
| } | ||||
|  | ||||
| ISR (TWI_vect) | ||||
| { | ||||
| 	switch (TWI_STATUS) | ||||
| 	{ | ||||
| 		// ----\/ ---- MASTER TRANSMITTER OR WRITING ADDRESS ----\/ ----  // | ||||
| 		case TWI_MT_SLAW_ACK: // SLA+W transmitted and ACK received | ||||
| 		// Set mode to Master Transmitter | ||||
| 		TWIInfo.mode = MasterTransmitter; | ||||
| 		case TWI_START_SENT: // Start condition has been transmitted | ||||
| 		case TWI_MT_DATA_ACK: // Data byte has been transmitted, ACK received | ||||
| 			if (TXBuffIndex < TXBuffLen) // If there is more data to send | ||||
| 			{ | ||||
| 				TWDR = TWITransmitBuffer[TXBuffIndex++]; // Load data to transmit buffer | ||||
| 				TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||||
| 				TWISendTransmit(); // Send the data | ||||
| 			} | ||||
| 			// This transmission is complete however do not release bus yet | ||||
| 			else if (TWIInfo.repStart) | ||||
| 			{ | ||||
| 				TWIInfo.errorCode = 0xFF; | ||||
| 				TWISendStart(); | ||||
| 			} | ||||
| 			// All transmissions are complete, exit | ||||
| 			else | ||||
| 			{ | ||||
| 				TWIInfo.mode = Ready; | ||||
| 				TWIInfo.errorCode = 0xFF; | ||||
| 				TWISendStop(); | ||||
| 			} | ||||
| 			break; | ||||
| 		 | ||||
| 		// ----\/ ---- MASTER RECEIVER ----\/ ----  // | ||||
| 		 | ||||
| 		case TWI_MR_SLAR_ACK: // SLA+R has been transmitted, ACK has been received | ||||
| 			// Switch to Master Receiver mode | ||||
| 			TWIInfo.mode = MasterReceiver; | ||||
| 			// If there is more than one byte to be read, receive data byte and return an ACK | ||||
| 			if (RXBuffIndex < RXBuffLen-1) | ||||
| 			{ | ||||
| 				TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||||
| 				TWISendACK(); | ||||
| 			} | ||||
| 			// Otherwise when a data byte (the only data byte) is received, return NACK | ||||
| 			else | ||||
| 			{ | ||||
| 				TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||||
| 				TWISendNACK(); | ||||
| 			} | ||||
| 			break; | ||||
| 		 | ||||
| 		case TWI_MR_DATA_ACK: // Data has been received, ACK has been transmitted. | ||||
| 		 | ||||
| 			/// -- HANDLE DATA BYTE --- /// | ||||
| 			TWIReceiveBuffer[RXBuffIndex++] = TWDR; | ||||
| 			// If there is more than one byte to be read, receive data byte and return an ACK | ||||
| 			if (RXBuffIndex < RXBuffLen-1) | ||||
| 			{ | ||||
| 				TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||||
| 				TWISendACK(); | ||||
| 			} | ||||
| 			// Otherwise when a data byte (the only data byte) is received, return NACK | ||||
| 			else | ||||
| 			{ | ||||
| 				TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||||
| 				TWISendNACK(); | ||||
| 			} | ||||
| 			break; | ||||
| 		 | ||||
| 		case TWI_MR_DATA_NACK: // Data byte has been received, NACK has been transmitted. End of transmission. | ||||
| 		 | ||||
| 			/// -- HANDLE DATA BYTE --- /// | ||||
| 			TWIReceiveBuffer[RXBuffIndex++] = TWDR;	 | ||||
| 			// This transmission is complete however do not release bus yet | ||||
| 			if (TWIInfo.repStart) | ||||
| 			{ | ||||
| 				TWIInfo.errorCode = 0xFF; | ||||
| 				TWISendStart(); | ||||
| 			} | ||||
| 			// All transmissions are complete, exit | ||||
| 			else | ||||
| 			{ | ||||
| 				TWIInfo.mode = Ready; | ||||
| 				TWIInfo.errorCode = 0xFF; | ||||
| 				TWISendStop(); | ||||
| 			} | ||||
| 			break; | ||||
| 		 | ||||
| 		// ----\/ ---- MT and MR common ----\/ ---- // | ||||
| 		 | ||||
| 		case TWI_MR_SLAR_NACK: // SLA+R transmitted, NACK received | ||||
| 		case TWI_MT_SLAW_NACK: // SLA+W transmitted, NACK received | ||||
| 		case TWI_MT_DATA_NACK: // Data byte has been transmitted, NACK received | ||||
| 		case TWI_LOST_ARBIT: // Arbitration has been lost | ||||
| 			// Return error and send stop and set mode to ready | ||||
| 			if (TWIInfo.repStart) | ||||
| 			{				 | ||||
| 				TWIInfo.errorCode = TWI_STATUS; | ||||
| 				TWISendStart(); | ||||
| 			} | ||||
| 			// All transmissions are complete, exit | ||||
| 			else | ||||
| 			{ | ||||
| 				TWIInfo.mode = Ready; | ||||
| 				TWIInfo.errorCode = TWI_STATUS; | ||||
| 				TWISendStop(); | ||||
| 			} | ||||
| 			break; | ||||
| 		case TWI_REP_START_SENT: // Repeated start has been transmitted | ||||
| 			// Set the mode but DO NOT clear TWINT as the next data is not yet ready | ||||
| 			TWIInfo.mode = RepeatedStartSent; | ||||
| 			break; | ||||
| 		 | ||||
| 		// ----\/ ---- SLAVE RECEIVER ----\/ ----  // | ||||
| 		 | ||||
| 		// TODO  IMPLEMENT SLAVE RECEIVER FUNCTIONALITY | ||||
| 		 | ||||
| 		// ----\/ ---- SLAVE TRANSMITTER ----\/ ----  // | ||||
| 		 | ||||
| 		// TODO  IMPLEMENT SLAVE TRANSMITTER FUNCTIONALITY | ||||
| 		 | ||||
| 		// ----\/ ---- MISCELLANEOUS STATES ----\/ ----  // | ||||
| 		case TWI_NO_RELEVANT_INFO: // It is not really possible to get into this ISR on this condition | ||||
| 								   // Rather, it is there to be manually set between operations | ||||
| 			break; | ||||
| 		case TWI_ILLEGAL_START_STOP: // Illegal START/STOP, abort and return error | ||||
| 			TWIInfo.errorCode = TWI_ILLEGAL_START_STOP; | ||||
| 			TWIInfo.mode = Ready; | ||||
| 			TWISendStop(); | ||||
| 			break; | ||||
| 	} | ||||
| 	 | ||||
| } | ||||
| @@ -1,82 +0,0 @@ | ||||
| /* | ||||
|  * TWIlib.h | ||||
|  * | ||||
|  * Created: 6/01/2014 10:38:42 PM | ||||
|  *  Author: Chris Herring | ||||
|  *  http://www.chrisherring.net/all/tutorial-interrupt-driven-twi-interface-for-avr-part1/ | ||||
|  */  | ||||
|  | ||||
|  | ||||
| #ifndef TWILIB_H_ | ||||
| #define TWILIB_H_ | ||||
| // TWI bit rate (was 100000) | ||||
| #define TWI_FREQ 400000 | ||||
| // Get TWI status | ||||
| #define TWI_STATUS	(TWSR & 0xF8)  | ||||
| // Transmit buffer length | ||||
| #define TXMAXBUFLEN 20 | ||||
| // Receive buffer length | ||||
| #define RXMAXBUFLEN 20 | ||||
| // Global transmit buffer | ||||
| uint8_t TWITransmitBuffer[TXMAXBUFLEN]; | ||||
| // Global receive buffer | ||||
| volatile uint8_t TWIReceiveBuffer[RXMAXBUFLEN]; | ||||
| // Buffer indexes | ||||
| volatile int TXBuffIndex; // Index of the transmit buffer. Is volatile, can change at any time. | ||||
| int RXBuffIndex; // Current index in the receive buffer | ||||
| // Buffer lengths | ||||
| int TXBuffLen; // The total length of the transmit buffer | ||||
| int RXBuffLen; // The total number of bytes to read (should be less than RXMAXBUFFLEN) | ||||
|  | ||||
| typedef enum { | ||||
| 	Ready, | ||||
| 	Initializing, | ||||
| 	RepeatedStartSent, | ||||
| 	MasterTransmitter, | ||||
| 	MasterReceiver, | ||||
| 	SlaceTransmitter, | ||||
| 	SlaveReciever | ||||
| 	} TWIMode; | ||||
|  | ||||
|  typedef struct TWIInfoStruct{ | ||||
| 	TWIMode mode; | ||||
| 	uint8_t errorCode; | ||||
| 	uint8_t repStart;	 | ||||
| 	}TWIInfoStruct; | ||||
| TWIInfoStruct TWIInfo; | ||||
|  | ||||
|  | ||||
| // TWI Status Codes | ||||
| #define TWI_START_SENT			0x08 // Start sent | ||||
| #define TWI_REP_START_SENT		0x10 // Repeated Start sent | ||||
| // Master Transmitter Mode | ||||
| #define TWI_MT_SLAW_ACK			0x18 // SLA+W sent and ACK received | ||||
| #define TWI_MT_SLAW_NACK		0x20 // SLA+W sent and NACK received | ||||
| #define TWI_MT_DATA_ACK			0x28 // DATA sent and ACK received | ||||
| #define TWI_MT_DATA_NACK		0x30 // DATA sent and NACK received | ||||
| // Master Receiver Mode | ||||
| #define TWI_MR_SLAR_ACK			0x40 // SLA+R sent, ACK received | ||||
| #define TWI_MR_SLAR_NACK		0x48 // SLA+R sent, NACK received | ||||
| #define TWI_MR_DATA_ACK			0x50 // Data received, ACK returned | ||||
| #define TWI_MR_DATA_NACK		0x58 // Data received, NACK returned | ||||
|  | ||||
| // Miscellaneous States | ||||
| #define TWI_LOST_ARBIT			0x38 // Arbitration has been lost | ||||
| #define TWI_NO_RELEVANT_INFO	0xF8 // No relevant information available | ||||
| #define TWI_ILLEGAL_START_STOP	0x00 // Illegal START or STOP condition has been detected | ||||
| #define TWI_SUCCESS				0xFF // Successful transfer, this state is impossible from TWSR as bit2 is 0 and read only | ||||
|  | ||||
|  | ||||
| #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. | ||||
| #define TWISendStop()		(TWCR = (1<<TWINT)|(1<<TWSTO)|(1<<TWEN)|(1<<TWIE)) // Send the STOP signal, enable interrupts and TWI, clear TWINT flag. | ||||
| #define TWISendTransmit()	(TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWIE)) // Used to resume a transfer, clear TWINT and ensure that TWI and interrupts are enabled. | ||||
| #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. | ||||
| #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. | ||||
|  | ||||
| // Function declarations | ||||
| uint8_t TWITransmitData(void *const TXdata, uint8_t dataLen, uint8_t repStart); | ||||
| void TWIInit(void); | ||||
| uint8_t TWIReadData(uint8_t TWIaddr, uint8_t bytesToRead, uint8_t repStart); | ||||
| uint8_t isTWIReady(void); | ||||
|  | ||||
| #endif // TWICOMMS_H_  | ||||
							
								
								
									
										149
									
								
								drivers/avr/i2c_master.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										149
									
								
								drivers/avr/i2c_master.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,149 @@ | ||||
| /* Library made by: g4lvanix | ||||
|  * Github repository: https://github.com/g4lvanix/I2C-master-lib | ||||
|  */ | ||||
|  | ||||
| #include <avr/io.h> | ||||
| #include <util/twi.h> | ||||
|  | ||||
| #include "i2c_master.h" | ||||
|  | ||||
| #define F_SCL 400000UL // SCL frequency | ||||
| #define Prescaler 1 | ||||
| #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2) | ||||
|  | ||||
| void i2c_init(void) | ||||
| { | ||||
| 	TWBR = (uint8_t)TWBR_val; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_start(uint8_t address) | ||||
| { | ||||
| 	// reset TWI control register | ||||
| 	TWCR = 0; | ||||
| 	// transmit START condition  | ||||
| 	TWCR = (1<<TWINT) | (1<<TWSTA) | (1<<TWEN); | ||||
| 	// wait for end of transmission | ||||
| 	while( !(TWCR & (1<<TWINT)) ); | ||||
| 	 | ||||
| 	// check if the start condition was successfully transmitted | ||||
| 	if((TWSR & 0xF8) != TW_START){ return 1; } | ||||
| 	 | ||||
| 	// load slave address into data register | ||||
| 	TWDR = address; | ||||
| 	// start transmission of address | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); | ||||
| 	// wait for end of transmission | ||||
| 	while( !(TWCR & (1<<TWINT)) ); | ||||
| 	 | ||||
| 	// check if the device has acknowledged the READ / WRITE mode | ||||
| 	uint8_t twst = TW_STATUS & 0xF8; | ||||
| 	if ( (twst != TW_MT_SLA_ACK) && (twst != TW_MR_SLA_ACK) ) return 1; | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_write(uint8_t data) | ||||
| { | ||||
| 	// load data into data register | ||||
| 	TWDR = data; | ||||
| 	// start transmission of data | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); | ||||
| 	// wait for end of transmission | ||||
| 	while( !(TWCR & (1<<TWINT)) ); | ||||
| 	 | ||||
| 	if( (TWSR & 0xF8) != TW_MT_DATA_ACK ){ return 1; } | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_read_ack(void) | ||||
| { | ||||
| 	 | ||||
| 	// start TWI module and acknowledge data after reception | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);  | ||||
| 	// wait for end of transmission | ||||
| 	while( !(TWCR & (1<<TWINT)) ); | ||||
| 	// return received data from TWDR | ||||
| 	return TWDR; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_read_nack(void) | ||||
| { | ||||
| 	 | ||||
| 	// start receiving without acknowledging reception | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN); | ||||
| 	// wait for end of transmission | ||||
| 	while( !(TWCR & (1<<TWINT)) ); | ||||
| 	// return received data from TWDR | ||||
| 	return TWDR; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length) | ||||
| { | ||||
| 	if (i2c_start(address | I2C_WRITE)) return 1; | ||||
| 	 | ||||
| 	for (uint16_t i = 0; i < length; i++) | ||||
| 	{ | ||||
| 		if (i2c_write(data[i])) return 1; | ||||
| 	} | ||||
| 	 | ||||
| 	i2c_stop(); | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length) | ||||
| { | ||||
| 	if (i2c_start(address | I2C_READ)) return 1; | ||||
| 	 | ||||
| 	for (uint16_t i = 0; i < (length-1); i++) | ||||
| 	{ | ||||
| 		data[i] = i2c_read_ack(); | ||||
| 	} | ||||
| 	data[(length-1)] = i2c_read_nack(); | ||||
| 	 | ||||
| 	i2c_stop(); | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length) | ||||
| { | ||||
| 	if (i2c_start(devaddr | 0x00)) return 1; | ||||
|  | ||||
| 	i2c_write(regaddr); | ||||
|  | ||||
| 	for (uint16_t i = 0; i < length; i++) | ||||
| 	{ | ||||
| 		if (i2c_write(data[i])) return 1; | ||||
| 	} | ||||
|  | ||||
| 	i2c_stop(); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length) | ||||
| { | ||||
| 	if (i2c_start(devaddr)) return 1; | ||||
|  | ||||
| 	i2c_write(regaddr); | ||||
|  | ||||
| 	if (i2c_start(devaddr | 0x01)) return 1; | ||||
|  | ||||
| 	for (uint16_t i = 0; i < (length-1); i++) | ||||
| 	{ | ||||
| 		data[i] = i2c_read_ack(); | ||||
| 	} | ||||
| 	data[(length-1)] = i2c_read_nack(); | ||||
|  | ||||
| 	i2c_stop(); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void i2c_stop(void) | ||||
| { | ||||
| 	// transmit STOP condition | ||||
| 	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO); | ||||
| } | ||||
							
								
								
									
										22
									
								
								drivers/avr/i2c_master.h
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										22
									
								
								drivers/avr/i2c_master.h
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| /* Library made by: g4lvanix | ||||
|  * Github repository: https://github.com/g4lvanix/I2C-master-lib | ||||
|  */ | ||||
|  | ||||
| #ifndef I2C_MASTER_H | ||||
| #define I2C_MASTER_H | ||||
|  | ||||
| #define I2C_READ 0x01 | ||||
| #define I2C_WRITE 0x00 | ||||
|  | ||||
| void i2c_init(void); | ||||
| uint8_t i2c_start(uint8_t address); | ||||
| uint8_t i2c_write(uint8_t data); | ||||
| uint8_t i2c_read_ack(void); | ||||
| uint8_t i2c_read_nack(void); | ||||
| uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length); | ||||
| uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length); | ||||
| uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); | ||||
| uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); | ||||
| void i2c_stop(void); | ||||
|  | ||||
| #endif // I2C_MASTER_H | ||||
| @@ -20,7 +20,7 @@ | ||||
| #include <avr/io.h> | ||||
| #include <util/delay.h> | ||||
| #include <string.h> | ||||
| #include "TWIlib.h" | ||||
| #include "i2c_master.h" | ||||
| #include "progmem.h" | ||||
|  | ||||
| // This is a 7-bit address, that gets left-shifted and bit 0 | ||||
| @@ -50,7 +50,7 @@ | ||||
| #define ISSI_BANK_FUNCTIONREG 0x0B    // helpfully called 'page nine' | ||||
|  | ||||
| // Transfer buffer for TWITransmitData() | ||||
| uint8_t g_twi_transfer_buffer[TXMAXBUFLEN]; | ||||
| uint8_t g_twi_transfer_buffer[20]; | ||||
|  | ||||
| // These buffers match the IS31FL3731 PWM registers 0x24-0xB3. | ||||
| // Storing them like this is optimal for I2C transfers to the registers. | ||||
| @@ -80,17 +80,11 @@ bool g_led_control_registers_update_required = false; | ||||
|  | ||||
| void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ) | ||||
| { | ||||
| 	g_twi_transfer_buffer[0] = (addr << 1) | 0x00; | ||||
| 	g_twi_transfer_buffer[1] = reg; | ||||
| 	g_twi_transfer_buffer[2] = data; | ||||
| 	g_twi_transfer_buffer[0] = reg; | ||||
| 	g_twi_transfer_buffer[1] = data; | ||||
|  | ||||
| 	// Set the error code to have no relevant information | ||||
| 	TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||||
| 	// Continuously attempt to transmit data until a successful transmission occurs | ||||
| 	//while ( TWIInfo.errorCode != 0xFF ) | ||||
| 	//{ | ||||
| 		TWITransmitData( g_twi_transfer_buffer, 3, 0 ); | ||||
| 	//} | ||||
| 	//Transmit data until succesful | ||||
| 	while(i2c_transmit(addr << 1, g_twi_transfer_buffer,2) != 0);  | ||||
| } | ||||
|  | ||||
| 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 ) | ||||
| 	// transmit PWM registers in 9 transfers of 16 bytes | ||||
| 	// g_twi_transfer_buffer[] is 20 bytes | ||||
|  | ||||
| 	// set the I2C address | ||||
| 	g_twi_transfer_buffer[0] = (addr << 1) | 0x00; | ||||
|  | ||||
| 	// iterate over the pwm_buffer contents at 16 byte intervals | ||||
| 	for ( int i = 0; i < 144; i += 16 ) | ||||
| 	{ | ||||
| 		// set the first register, e.g. 0x24, 0x34, 0x44, etc. | ||||
| 		g_twi_transfer_buffer[1] = 0x24 + i; | ||||
| 		g_twi_transfer_buffer[0] = 0x24 + i; | ||||
| 		// copy the data from i to i+15 | ||||
| 		// device will auto-increment register for data after the first byte | ||||
| 		// thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer | ||||
| 		for ( int j = 0; j < 16; j++ ) | ||||
| 		{ | ||||
| 			g_twi_transfer_buffer[2 + j] = pwm_buffer[i + j]; | ||||
| 			g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; | ||||
| 		} | ||||
|  | ||||
| 		// Set the error code to have no relevant information | ||||
| 		TWIInfo.errorCode = TWI_NO_RELEVANT_INFO; | ||||
| 		// Continuously attempt to transmit data until a successful transmission occurs | ||||
| 		while ( TWIInfo.errorCode != 0xFF ) | ||||
| 		{ | ||||
| 			TWITransmitData( g_twi_transfer_buffer, 16 + 2, 0 ); | ||||
| 		} | ||||
| 		//Transmit buffer until succesful | ||||
| 		while(i2c_transmit(addr << 1, g_twi_transfer_buffer,17) != 0); | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,7 @@ | ||||
|  | ||||
| #include "rgb_matrix.h" | ||||
| #include <avr/io.h> | ||||
| #include "TWIlib.h" | ||||
| #include "i2c_master.h" | ||||
| #include <util/delay.h> | ||||
| #include <avr/interrupt.h> | ||||
| #include "progmem.h" | ||||
| @@ -722,10 +722,8 @@ void rgb_matrix_indicators_user(void) {} | ||||
| // } | ||||
|  | ||||
| void rgb_matrix_init_drivers(void) { | ||||
|     //sei(); | ||||
|  | ||||
|     // Initialize TWI | ||||
|     TWIInit(); | ||||
|     i2c_init(); | ||||
|     IS31FL3731_init( DRIVER_ADDR_1 ); | ||||
|     IS31FL3731_init( DRIVER_ADDR_2 ); | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user