typedef struct I2C_Buffer {
- volatile uint16_t head;
- volatile uint16_t tail;
- volatile uint8_t sequencePos;
- volatile uint16_t size;
- volatile uint8_t *buffer;
+ uint16_t head;
+ uint16_t tail;
+ uint8_t sequencePos;
+ uint16_t size;
+ uint8_t *buffer;
} I2C_Buffer;
// ----- Function Declarations -----
uint8_t I2C_TxBufferPop();
void I2C_BufferPush( uint8_t byte, I2C_Buffer *buffer );
uint16_t I2C_BufferLen( I2C_Buffer *buffer );
+uint8_t I2C_Send( uint8_t *data, uint8_t sendLen, uint8_t recvLen );
// Scan Module command dictionary
CLIDict_Entry( echo, "Example command, echos the arguments." );
-CLIDict_Entry( i2cRecv, "Send I2C sequence of bytes and expect a reply of 1 byte." );
-CLIDict_Entry( i2cSend, "Send I2C sequence of bytes." );
+CLIDict_Entry( i2cRecv, "Send I2C sequence of bytes and expect a reply of 1 byte on the last sequence. Use |'s to split sequences with a stop." );
+CLIDict_Entry( i2cSend, "Send I2C sequence of bytes. Use |'s to split sequences with a stop." );
CLIDict_Entry( ledZero, "Zero out LED register pages (non-configuration)." );
CLIDict_Def( scanCLIDict, "Scan Module Commands" ) = {
volatile uint8_t I2C_TxBufferPtr[ I2C_TxBufferLength ];
volatile uint8_t I2C_RxBufferPtr[ I2C_TxBufferLength ];
-volatile I2C_Buffer I2C_TxBuffer = { 0, 0, 0, I2C_TxBufferLength, I2C_TxBufferPtr };
-volatile I2C_Buffer I2C_RxBuffer = { 0, 0, 0, I2C_RxBufferLength, I2C_RxBufferPtr };
+volatile I2C_Buffer I2C_TxBuffer = { 0, 0, 0, I2C_TxBufferLength, (uint8_t*)I2C_TxBufferPtr };
+volatile I2C_Buffer I2C_RxBuffer = { 0, 0, 0, I2C_RxBufferLength, (uint8_t*)I2C_RxBufferPtr };
void I2C_setup()
{
}
else
{
+ dbug_print("Attempting to read byte");
I2C0_C1 = I2C_RxBuffer.sequencePos == 1
? I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TXAK // Single byte read
: I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST; // Multi-byte read
}
else
{
+ /*
dbug_msg("STOP - ");
printHex( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) );
print(NL);
+ */
+
+ // Delay around STOP to make sure it actually happens...
+ delayMicroseconds( 1 );
+ I2C0_C1 = I2C_C1_IICEN; // Send STOP
+ delayMicroseconds( 7 );
// If there is another sequence, start sending
if ( I2C_BufferLen( (I2C_Buffer*)&I2C_TxBuffer ) < I2C_TxBuffer.size )
{
- // Check to see if we already have control of the bus
- if ( I2C0_C1 & I2C_C1_MST )
- {
- // Already the master (ah yeah), send a repeated start
- I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_RSTA | I2C_C1_TX;
- }
- // Otherwise, seize control
- else
- {
- // Wait...till the master dies
- while ( I2C0_S & I2C_S_BUSY );
-
- // Now we're the master (ah yisss), get ready to send stuffs
- I2C0_C1 = I2C_C1_IICEN | I2C_C1_MST | I2C_C1_TX;
- }
+ // Clear status flags
+ I2C0_S = I2C_S_IICIF | I2C_S_ARBL;
+
+ // Wait...till the master dies
+ while ( I2C0_S & I2C_S_BUSY );
// Enable I2C interrupt
I2C0_C1 = I2C_C1_IICEN | I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX;
// Transmit byte
I2C0_D = I2C_TxBufferPop();
}
- // Issue STOP
- else
- {
- delayMicroseconds( 1 ); // Should be enough time before issuing STOP
- I2C0_C1 = I2C_C1_IICEN; // Send STOP
- }
}
}
// Master Mode Receive
// ----- Functions -----
+void LED_zeroPages( uint8_t startPage, uint8_t numPages, uint8_t pageLen )
+{
+ // Page Setup
+ uint8_t pageSetup[] = { 0xE8, 0xFD, 0x00 };
+
+ // Max length of a page + chip id + reg start
+ uint8_t fullPage[ 0xB3 + 2 ] = { 0 };
+ fullPage[0] = 0xE8; // Set chip id, starting reg is already 0x00
+
+ // Iterate through given pages, zero'ing out the given register regions
+ for ( uint8_t page = startPage; page < startPage + numPages; page++ )
+ {
+ // Set page
+ pageSetup[2] = page;
+
+ // Setup page
+ while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 )
+ delay(1);
+
+ // Zero out page
+ while ( I2C_Send( fullPage, pageLen + 2, 0 ) == 0 )
+ delay(1);
+ }
+}
+
+
// Setup
inline void LED_setup()
{
I2C_setup();
+
+ // Zero out Frame Registers
+ LED_zeroPages( 0x00, 8, 0xB3 ); // LED Registers
+ LED_zeroPages( 0x0B, 1, 0x0C ); // Control Registers
+
+ // Disable Hardware shutdown of ISSI chip (pull high)
+ GPIOD_PDDR |= (1<<1);
+ PORTD_PCR1 = PORT_PCR_SRE | PORT_PCR_DSE | PORT_PCR_MUX(1);
+ GPIOD_PSOR |= (1<<1);
}
// Decrement buffer sequence (until next stop will be sent)
I2C_TxBuffer.sequencePos--;
+ /*
dbug_msg("Popping: ");
printHex( data );
print(" ");
print(" ");
printHex( I2C_TxBuffer.sequencePos );
print(NL);
+ */
return data;
}
// Depending on what type of transfer, the first byte is configured for R or W
I2C0_D = I2C_TxBufferPop();
+
return 1;
}
}
-void LED_zeroPages( uint8_t startPage, uint8_t numPages, uint8_t pageLen )
-{
- // Page Setup
- uint8_t pageSetup[] = { 0xE8, 0xFD, 0x00 };
-
- // Max length of a page + chip id + reg start
- uint8_t fullPage[ 0xB3 + 2 ] = { 0 };
- fullPage[0] = 0xE8; // Set chip id, starting reg is already 0x00
-
- // Iterate through given pages, zero'ing out the given register regions
- for ( uint8_t page = startPage; page < startPage + numPages; page++ )
- {
- // Set page
- pageSetup[2] = page;
-
- // Setup page
- while ( I2C_Send( pageSetup, sizeof( pageSetup ), 0 ) == 0 )
- delay(1);
-
- // Zero out page
- while ( I2C_Send( fullPage, pageLen + 2, 0 ) == 0 )
- delay(1);
- }
-}
-
-
// LED State processing loop
inline uint8_t LED_loop()
if ( *arg1Ptr == '\0' )
break;
+ // If | is found, end sequence and start new one
+ if ( *arg1Ptr == '|' )
+ {
+ print("| ");
+ I2C_Send( buffer, bufferLen, 0 );
+ bufferLen = 0;
+ continue;
+ }
+
// Interpret the argument
buffer[ bufferLen++ ] = (uint8_t)numToInt( arg1Ptr );
if ( *arg1Ptr == '\0' )
break;
+ // If | is found, end sequence and start new one
+ if ( *arg1Ptr == '|' )
+ {
+ print("| ");
+ I2C_Send( buffer, bufferLen, 0 );
+ bufferLen = 0;
+ continue;
+ }
+
// Interpret the argument
buffer[ bufferLen++ ] = (uint8_t)numToInt( arg1Ptr );