Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated i2c Part 3_slave states and read/write functionality #10

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added doc/I2C_Lab_Pt3.pdf
Binary file not shown.
5 changes: 4 additions & 1 deletion projects/lpc40xx_freertos/assignment_include.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,7 @@
* Take care to enable only one part macro enabled while compiling.
*/

#endif
#define I2C_LAB_ASSGNMT
//#define I2C_LAB_ASSGNMT_PART_A
#define I2C_LAB_ASSGNMT_PART_B
#endif
2 changes: 2 additions & 0 deletions projects/lpc40xx_freertos/l3_drivers/i2c.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,5 @@ bool i2c__write_single(i2c_e i2c_number, uint8_t slave_address, uint8_t slave_me
*/
bool i2c__write_slave_data(i2c_e i2c_number, uint8_t slave_address, uint8_t starting_slave_memory_address,
const uint8_t *bytes_to_write, uint32_t number_of_bytes);

void i2c2__slave_init(uint8_t slave_address_to_respond_to);
17 changes: 17 additions & 0 deletions projects/lpc40xx_freertos/l3_drivers/i2c_slave_function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once
#include <stdbool.h>
#include <stdint.h>

/**
* This function is responsible for reading slave memory
* @param memory_index The index of Slave memory need to be read
* @param *memory Reference of variable to be updated with salve memory data
*/
bool i2c_slave_callback__read_memory(uint8_t memory_index, uint8_t *memory);

/**
* This function is responsible for writing slave memory
* @param memory_index The index of Slave memory need to be read
* @param *memory Reference of variable to be updated with salve memory data
*/
bool i2c_slave_callback__write_memory(uint8_t memory_index, uint8_t memory_value);
98 changes: 97 additions & 1 deletion projects/lpc40xx_freertos/l3_drivers/sources/i2c.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,12 @@
#include "task.h"

#include "common_macros.h"
#include "i2c_slave_function.h"
#include "lpc40xx.h"
#include "lpc_peripherals.h"

/// Set to non-zero to enable debugging, and then you can use I2C__DEBUG_PRINTF()
#define I2C__ENABLE_DEBUGGING 0
#define I2C__ENABLE_DEBUGGING 1

#if I2C__ENABLE_DEBUGGING
#include <stdio.h>
Expand Down Expand Up @@ -44,6 +45,11 @@ typedef struct {
uint8_t *input_byte_pointer; ///< Used for reading I2C slave device
const uint8_t *output_byte_pointer; ///< Used for writing data to the I2C slave device
size_t number_of_bytes_to_transfer;

// Slave parameters
bool slave_data_address_received;
uint8_t slave_data_address;
uint8_t slave_data_count;
} i2c_s;

/// Instances of structs for each I2C peripheral
Expand Down Expand Up @@ -153,6 +159,18 @@ void i2c__initialize(i2c_e i2c_number, uint32_t desired_i2c_bus_speed_in_hz, uin
lpc_peripheral__enable_interrupt(peripheral_id, isrs[i2c_number], i2c_structs[i2c_number].rtos_isr_trace_name);
}

#ifdef I2C_LAB_ASSGNMT

void i2c2__slave_init(uint8_t slave_address_to_respond_to) {
const uint8_t device_address_bitmask = (0b11111110);
const uint8_t i2c_enable_bit_mask = (1 << 6);
const uint8_t ack_own_slave_addr_bit_mask = (1 << 2);
LPC_I2C0->ADR0 |= ((slave_address_to_respond_to << 1) & device_address_bitmask);
LPC_I2C0->CONSET |= (i2c_enable_bit_mask | ack_own_slave_addr_bit_mask);
}

#endif

bool i2c__detect(i2c_e i2c_number, uint8_t slave_address) {
// The I2C State machine will not continue after 1st state when length is set to 0
const size_t zero_bytes = 0;
Expand Down Expand Up @@ -233,6 +251,7 @@ static bool i2c__transfer_unprotected(i2c_s *i2c, uint8_t slave_address, uint8_t
// We cannot block on the semaphore if the RTOS is not running, so eat the CPU until transaction is done
while (!xSemaphoreTake(i2c->transfer_complete_signal, 0)) {
}
printf("Error Code is %d\n", i2c->error_code);
status = (0 == i2c->error_code);
}

Expand Down Expand Up @@ -274,6 +293,20 @@ static bool i2c__handle_state_machine(i2c_s *i2c) {
I2C__STATE_MR_SLAVE_READ_NACK = 0x48,
I2C__STATE_MR_SLAVE_ACK_SENT = 0x50,
I2C__STATE_MR_SLAVE_NACK_SENT = 0x58,

#ifdef I2C_LAB_ASSGNMT_PART_B
// Slave Receiver Mode (SR):
I2C__STATE_SR_SLAVE_ADDRESS_RECEIVED = 0x60,
I2C__STATE_SR_MASTER_DATA_RECEIVED = 0x80,
I2C__STATE_SR_MASTER_LAST_DATA_RECEIVED = 0x88,
I2C__STATE_SR_MASTER_STOP_RECEIVED = 0xA0,

// Slave Trasmitter Mode (ST):
I2C__STATE_ST_SLAVE_ADDRESS_RECEIVED = 0xA8,
I2C__STATE_ST_MASTER_ACK_RECEIVED = 0xB8,
I2C__STATE_ST_MASTER_NACK_RECEIVED = 0xC0,
I2C__STATE_ST_LAST_DATA_BYTE_TRANS_ACK_RECEIVED = 0xC8,
#endif
};

bool stop_sent = false;
Expand All @@ -295,6 +328,8 @@ static bool i2c__handle_state_machine(i2c_s *i2c) {
const unsigned i2c_state = lpc_i2c->STAT;
I2C__DEBUG_PRINTF(" HW State: 0x%02X", i2c_state);

uint8_t data_received_from_master;
uint8_t read_slave_data;
switch (i2c_state) {
// Start condition sent, so send the device address
case I2C__STATE_START:
Expand Down Expand Up @@ -382,6 +417,67 @@ static bool i2c__handle_state_machine(i2c_s *i2c) {
i2c->error_code = lpc_i2c->STAT;
break;

#ifdef I2C_LAB_ASSGNMT_PART_B

case I2C__STATE_SR_SLAVE_ADDRESS_RECEIVED:
i2c__set_ack_flag(lpc_i2c);
i2c__clear_si_flag_for_hw_to_take_next_action(lpc_i2c);
i2c->slave_data_address_received = false;
break;

case I2C__STATE_SR_MASTER_DATA_RECEIVED:
data_received_from_master = (lpc_i2c->DAT & 0xFF);
if (!i2c->slave_data_address_received) {
i2c->slave_data_address = data_received_from_master;
i2c->slave_data_count = 0;
i2c__set_ack_flag(lpc_i2c);
i2c->slave_data_address_received = true;
} else {
if (i2c_slave_callback__write_memory(i2c->slave_data_address + i2c->slave_data_count,
data_received_from_master)) {
i2c__set_ack_flag(lpc_i2c);
i2c->slave_data_count++;
} else {
i2c__set_nack_flag(lpc_i2c);
}
}
i2c__clear_si_flag_for_hw_to_take_next_action(lpc_i2c);
break;

case I2C__STATE_SR_MASTER_STOP_RECEIVED:
i2c__set_ack_flag(lpc_i2c);
i2c__clear_si_flag_for_hw_to_take_next_action(lpc_i2c);
break;

case I2C__STATE_ST_SLAVE_ADDRESS_RECEIVED:
fprintf(stderr, "read data from %d\n", i2c->slave_data_address);
if (i2c_slave_callback__read_memory(i2c->slave_data_address, &read_slave_data)) {
lpc_i2c->DAT = read_slave_data;
i2c__set_ack_flag(lpc_i2c);
i2c->slave_data_count++;
} else {
i2c__set_nack_flag(lpc_i2c);
}
i2c__clear_si_flag_for_hw_to_take_next_action(lpc_i2c);
break;

case I2C__STATE_ST_MASTER_ACK_RECEIVED:
if (i2c_slave_callback__read_memory(i2c->slave_data_address + i2c->slave_data_count, &read_slave_data)) {
lpc_i2c->DAT = read_slave_data;
i2c__set_ack_flag(lpc_i2c);
i2c->slave_data_count++;
} else {
i2c__set_nack_flag(lpc_i2c);
}
i2c__clear_si_flag_for_hw_to_take_next_action(lpc_i2c);
break;

case I2C__STATE_ST_MASTER_NACK_RECEIVED:
// i2c__set_ack_flag(lpc_i2c);
i2c__clear_si_flag_for_hw_to_take_next_action(lpc_i2c);
break;

#endif
case I2C__STATE_MT_SLAVE_ADDR_NACK: // no break
case I2C__STATE_MT_SLAVE_DATA_NACK: // no break
case I2C__STATE_MR_SLAVE_READ_NACK: // no break
Expand Down
34 changes: 34 additions & 0 deletions projects/lpc40xx_freertos/l3_drivers/sources/i2c_slave_function.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "i2c_slave_function.h"
#include "i2c.h"

#define SLAVE_MEMORY_SIZE 10

/**
* Register number = memory Index
* Reg 0: On/Off
* | Led 3 | Led 2 | Led 1 | Led 0 | | | | |
* | Reserved |
*
* Reg 1: Blinking
* | Led3 | Led2 | Led 1| Led 0| | | | on/off(blinking)|
* | Blinking duration|
*/

static volatile uint8_t slave_memory[SLAVE_MEMORY_SIZE];

bool i2c_slave_callback__read_memory(uint8_t memory_index, uint8_t *memory) {
if (memory_index < SLAVE_MEMORY_SIZE) {
*memory = slave_memory[memory_index];
} else {
return false;
}
return true;
}

bool i2c_slave_callback__write_memory(uint8_t memory_index, uint8_t memory_value) {
if (memory_index < SLAVE_MEMORY_SIZE)
slave_memory[memory_index] = memory_value;
else
return false;
return true;
}
Loading