// Note this program is designed to pair with c_client. // The i2c connection may be made directly between the two Arduino SDA and SCL pins. // No i2c pullup resistors are require.d #define F_CPU 16000000UL #define BAUD 38400 #include #include #include #include "twi.h" //------------------------------------------------------------------------------ #define SER_BUF_N (16) // size of receive buffer // Note that 'ser_buf_i_idx' must be declared volatile or the // the compare in the main loop will not work. volatile int ser_buf_i_idx = 0; // receive buffer input index int ser_buf_o_idx = 0; // receive buffer output index // Receive buffer char ser_buf[ SER_BUF_N ]; void uart_init(void) { UBRR0H = UBRRH_VALUE; UBRR0L = UBRRL_VALUE; #if USE_2X UCSR0A |= _BV(U2X0); #else UCSR0A &= ~(_BV(U2X0)); #endif UCSR0C = _BV(UCSZ01) | _BV(UCSZ00); // 8-bit data UCSR0B = _BV(RXEN0) | _BV(TXEN0) | _BV(RXCIE0); // Enable RX and TX and RX intertupt enable } void uart_putchar(char c) { loop_until_bit_is_set(UCSR0A, UDRE0); // Wait until data register empty. UDR0 = c; } void uart_putchar_alt(char c) { UDR0 = c; loop_until_bit_is_set(UCSR0A, TXC0); // Wait until transmission ready. } char uart_getchar(void) { loop_until_bit_is_set(UCSR0A, RXC0); // Wait until data exists. return UDR0; } //------------------------------------------------------------------------------ #define I2C_LOCAL_ADDR (9) #define I2C_REMOTE_ADDR (8) #define I2C_BUF_N (16) static uint8_t i2c_buf[ I2C_BUF_N ]; static volatile uint8_t i2c_buf_i_idx = 0; static uint8_t i2c_buf_o_idx = 0; static uint8_t last_char = '0'; void i2c_read_from( uint8_t i2c_addr, uint8_t dev_reg_addr, uint8_t read_byte_cnt ) { uint8_t recv_char = '0'; const uint8_t kWaitFl = 1; const uint8_t kSendStopFl = 1; const uint8_t kNoSendStopFl = 0; // Request to read from the client. Note that 'sendStop'==0. // Use this call to tell the client what data should be sent // during the subsequent twi_readFrom(). twi_writeTo(i2c_addr, &dev_reg_addr, 1, kWaitFl, kNoSendStopFl); // Blocking waiting and wait to read the client's response. for( uint8_t i=0; i i2c_read_from() // 'w', i2c-addr, reg-idx, cnt, value0, ... valueN -> i2c_xmit() switch(state) { case kWait_for_cmd: if(c == 'w' || c == 'r') { cmd = c; state = kWait_for_i2c; } else uart_putchar('E'); // indicate a protocol error break; case kWait_for_i2c: i2c_addr = (uint8_t)c; state = kWait_for_reg; break; case kWait_for_reg: dev_reg_addr = (uint8_t)c; state = kWait_for_cnt; break; case kWait_for_cnt: op_byte_cnt = (uint8_t)c; if( cmd == 'r' ) { i2c_read_from( i2c_addr, dev_reg_addr, op_byte_cnt ); state = kWait_for_cmd; } else { // TODO: handle case where there are no data bytes (only e.g. note-off) state = kWait_for_value; data_buf[0] = dev_reg_addr; // make 'dev_reg_addr' the first data value to write data_buf_idx = 1; // op_byte_cnt += 1; // incr op_byte_cnt to account for 'dev_reg_addr' as first byte } break; case kWait_for_value: if( data_buf_idx >= data_bufN ) { uart_putchar('F'); // indicate a buffer overrun state = kWait_for_cmd; } else { data_buf[ data_buf_idx++ ] = c; if(data_buf_idx == op_byte_cnt ) { /* uint8_t ii; for(ii=0; ii