static bool i2c_isr(void) { bool handled = false; if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_STOP_DET_MASK) { i2c_data_read(); write(QUARKX1000_IC_INTR_MASK, 0); read(QUARKX1000_IC_CLR_INTR); if (device.direction == I2C_DIRECTION_WRITE) { if (device.config.cb_tx) device.config.cb_tx(); } else { if (device.config.cb_rx) device.config.cb_rx(); } handled = true; } if (read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK) { i2c_data_send(); if (device.rx_tx_len <= 0) { set_value(QUARKX1000_IC_INTR_MASK, QUARKX1000_IC_INTR_STAT_TX_EMPTY_MASK, QUARKX1000_IC_INTR_STAT_TX_EMPTY_SHIFT, 0); set_value(QUARKX1000_IC_INTR_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_MASK, QUARKX1000_IC_INTR_STAT_STOP_DET_SHIFT, 1); } handled = true; } if(read(QUARKX1000_IC_INTR_STAT) & QUARKX1000_IC_INTR_STAT_RX_FULL_MASK) { i2c_data_read(); handled = true; } if (read(QUARKX1000_IC_INTR_STAT) & (QUARKX1000_IC_INTR_STAT_TX_ABRT_MASK | QUARKX1000_IC_INTR_STAT_TX_OVER_MASK | QUARKX1000_IC_INTR_STAT_RX_OVER_MASK | QUARKX1000_IC_INTR_STAT_RX_UNDER_MASK)) { write(QUARKX1000_IC_INTR_MASK, 0); read(QUARKX1000_IC_CLR_INTR); if (device.config.cb_err) device.config.cb_err(); handled = true; } return handled; }
/* receives an acknowledge from I2C rountine. * * @return value: 0--Ack received; 1--Nack received * */ static int i2c_receive_ack(void) { int nack; unsigned char regvalue; DELAY(1); regvalue = HW_REG(GPIO_0_DIR); regvalue &= (~SDA); HW_REG(GPIO_0_DIR) = regvalue; DELAY(1); i2c_clr(SCL); DELAY(1); i2c_set(SCL); DELAY(1); nack = i2c_data_read(); DELAY(1); i2c_clr(SCL); DELAY(1); // i2c_set(SDA); // DELAY(1); if (nack == 0) return 1; return 0; }
/* receives a character from I2C rountine. * * @return value: character received * */ static unsigned char i2c_receive_byte(void) { int j=0; int i; unsigned char regvalue; local_irq_disable(); for (i=0; i<8; i++) { DELAY(1); i2c_clr(SCL); DELAY(1); i2c_set(SCL); regvalue = HW_REG(GPIO_0_DIR); regvalue &= (~SDA); HW_REG(GPIO_0_DIR) = regvalue; DELAY(1); if (i2c_data_read()) j+=(1<<(7-i)); DELAY(1); i2c_clr(SCL); } local_irq_enable(); DELAY(1); // i2c_clr(SDA); // DELAY(1); return j; }
static int i2c_receive_ack(int Grp) { int nack; unsigned char regvalue; DELAY(1); regvalue = HW_REG(GPIO_I2C_DIR[Grp]); regvalue &= (~GPIO_I2C_BIT[Grp][PINI2C_SDA]); HW_REG(GPIO_I2C_DIR[Grp]) = regvalue; DELAY(1); i2c_clr(Grp, PINI2C_SCL); DELAY(1); i2c_set(Grp, PINI2C_SCL); DELAY(1); nack = i2c_data_read(Grp); DELAY(1); i2c_clr(Grp, PINI2C_SCL); DELAY(1); return !nack; }
static unsigned char i2c_receive_byte(int Grp) { int j = 0; int i; unsigned char regvalue; local_irq_disable(); for (i = 0; i < 8; i ++) { DELAY(1); i2c_clr(Grp, PINI2C_SCL); DELAY(2); i2c_set(Grp, PINI2C_SCL); regvalue = HW_REG(GPIO_I2C_DIR[Grp]); regvalue &= (~GPIO_I2C_BIT[Grp][PINI2C_SDA]); HW_REG(GPIO_I2C_DIR[Grp]) = regvalue; DELAY(1); if (i2c_data_read(Grp)) { j+=(1<<(7-i)); } DELAY(1); i2c_clr(Grp, PINI2C_SCL); } local_irq_enable(); DELAY(1); return j; }
static int i2c_polling_operation(uint8_t *write_buf, uint8_t write_len, uint8_t *read_buf, uint8_t read_len, uint16_t addr) { uint32_t start_time, intr_mask_stat; if (!(read(QUARKX1000_IC_CON) & QUARKX1000_IC_CON_MASTER_MODE_MASK)) return -1; /* Wait i2c idle */ start_time = clock_seconds(); while (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK) { if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) { return -1; } } /* Get interrupt mask to restore in the end of polling operation */ intr_mask_stat = read(QUARKX1000_IC_INTR_MASK); i2c_operation_setup(write_buf, write_len, read_buf, read_len, addr); /* Enable controller */ set_value(QUARKX1000_IC_ENABLE, QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 1); /* Transmit */ if (device.tx_len != 0) { while (device.tx_len > 0) { start_time = clock_seconds(); while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_TFNF_MASK)) { if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) { set_value(QUARKX1000_IC_ENABLE, QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0); return -1; } } i2c_data_send(); } start_time = clock_seconds(); while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_TFE_MASK)) { if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) { set_value(QUARKX1000_IC_ENABLE, QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0); return -1; } } } i2c_data_send(); /* Receive */ if (device.rx_len != 0) { while (device.rx_len > 0) { start_time = clock_seconds(); while (!(read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_RFNE_MASK)) { if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) { set_value(QUARKX1000_IC_ENABLE, QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0); return -1; } } i2c_data_read(); } } /* Stop Det */ start_time = clock_seconds(); while (!(read(QUARKX1000_IC_RAW_INTR_STAT) & QUARKX1000_IC_INTR_STAT_STOP_DET_MASK)) { if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) { set_value(QUARKX1000_IC_ENABLE, QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0); return -1; } } read(QUARKX1000_IC_CLR_STOP_DET); /* Wait i2c idle */ start_time = clock_seconds(); while (read(QUARKX1000_IC_STATUS) & QUARKX1000_IC_STATUS_ACTIVITY_MASK) { if ((clock_seconds() - start_time) > I2C_POLLING_TIMEOUT) { set_value(QUARKX1000_IC_ENABLE, QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0); return -1; } } /* Disable controller */ set_value(QUARKX1000_IC_ENABLE, QUARKX1000_IC_ENABLE_MASK, QUARKX1000_IC_ENABLE_SHIFT, 0); /* Restore interrupt mask */ write(QUARKX1000_IC_INTR_MASK, intr_mask_stat); return 0; }
static void decode_i2cstat(lpc17xx_i2c_config_t *config, int status) { error_code_t error = NO_ERROR; i2c_command_t *cmd = config->buffer; if (cmd->expected_status != status || status == ERROR) { cmd->expected_status = ERROR; //TODO: Should I issue a STOP command? } else { switch (status) { case START: //Send Address byte. //After Sending the address, next status should be SLA+W ACK. error = i2c_clear_start(config); cmd->expected_status = MASTER_SLAVEWr_ACK ; error |= i2c_address(config, WRITE); break; case MASTER_SLAVEWr_ACK: //Send Register to Write. error = i2c_reg(config); cmd->expected_status = MASTER_DATAWr_ACK; break; case MASTER_DATAWr_ACK: //If operation is read, RESTART. if (cmd->operation == READ) { cmd->expected_status = RESTART; error = i2c_set_start(config); //Else,just send the data. } else if (cmd->data_written < cmd->size ) { error = i2c_data_write(config, cmd->data[cmd->data_written]); cmd->data_written++; //If previous send was the last byte, then next should be STOP. } else { cmd->expected_status = IDLE; error = i2c_stop(config); } break; case RESTART: //Send address byte, with direction bit set to READ. I2C will ACK the address. error = i2c_clear_start(config); cmd->expected_status = MASTER_SLARd_ACK ; error |= i2c_address(config, READ); break; case MASTER_SLARd_ACK: //I2C will receive the first byte, set the ACK bit. if (cmd->data_written == ( cmd->size - 1) ) { error |= i2c_clear_ack(config); cmd->expected_status = MASTER_DATARd_NAK; } else { error = i2c_set_ack(config); cmd->expected_status = MASTER_DATARd_ACK; } break; case MASTER_DATARd_ACK: error = i2c_data_read(config); //A byte of data was received. cmd->data_written++; if (cmd->data_written == ( cmd->size - 1) ) { //The next byte will be the last byte, send a NAK. error |= i2c_clear_ack(config); cmd->expected_status = MASTER_DATARd_NAK; } else { error |= i2c_set_ack(config); cmd->expected_status = MASTER_DATARd_ACK; } break; case MASTER_DATARd_NAK: error = i2c_data_read(config); cmd->expected_status = IDLE; i2c_stop(config); break; default: break; } } if (error != NO_ERROR) { cmd->expected_status = ERROR; } i2c_clear_interrupt(config); }