- Initial commit of base firmware - which is still very raw
This commit is contained in:
160
Firmware/I2C_Master.c
Normal file
160
Firmware/I2C_Master.c
Normal file
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* I2C_Master.c
|
||||
*
|
||||
* Created: Sun Sep 11 2022 12:00:14
|
||||
* Author Chris
|
||||
*/
|
||||
|
||||
// ============================================================================================
|
||||
// Includes
|
||||
#include "I2C_Master.h"
|
||||
|
||||
#include "pico/malloc.h"
|
||||
#include "hardware/i2c.h"
|
||||
#include "hardware/dma.h"
|
||||
#include "hardware/irq.h"
|
||||
|
||||
|
||||
// ============================================================================================
|
||||
// Defines
|
||||
#define I2C_HARDWARE_UNIT (&i2c1_inst)
|
||||
#define I2C_BAUDRATE_HZ 400000UL
|
||||
|
||||
#define I2C_SCL_PIN 7
|
||||
#define I2C_SDA_PIN 6
|
||||
|
||||
|
||||
// ============================================================================================
|
||||
// Variables
|
||||
static bool _DMA_Transfer_Complete;
|
||||
static int _DMA_Transmit_Claim;
|
||||
static dma_channel_config _DMA_Transmit_Channel;
|
||||
|
||||
|
||||
// ============================================================================================
|
||||
// Function Declarations
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
Interrupt Service Routines
|
||||
*******************************************************************/
|
||||
void ISR_I2C_DMA_Transmit_Complete()
|
||||
{
|
||||
dma_hw->ints0 = (1u << _DMA_Transmit_Claim);
|
||||
|
||||
_DMA_Transfer_Complete = true;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
Functions
|
||||
*******************************************************************/
|
||||
void I2CM_Init(bool use_internal_pullups)
|
||||
{
|
||||
i2c_init(I2C_HARDWARE_UNIT, I2C_BAUDRATE_HZ);
|
||||
gpio_set_function(I2C_SDA_PIN, GPIO_FUNC_I2C);
|
||||
gpio_set_function(I2C_SCL_PIN, GPIO_FUNC_I2C);
|
||||
|
||||
/* Function for internal pull-ups has not been tested yet */
|
||||
if(use_internal_pullups == true)
|
||||
{
|
||||
gpio_pull_up(I2C_SDA_PIN);
|
||||
gpio_pull_up(I2C_SCL_PIN);
|
||||
}
|
||||
|
||||
|
||||
// Configura DMA Channel for SPI Transmit function
|
||||
_DMA_Transmit_Claim = dma_claim_unused_channel(false);
|
||||
_DMA_Transmit_Channel = dma_channel_get_default_config(_DMA_Transmit_Claim);
|
||||
|
||||
// channel_config_set_transfer_data_size(&_DMA_Transmit_Channel, DMA_SIZE_8);
|
||||
channel_config_set_transfer_data_size(&_DMA_Transmit_Channel, DMA_SIZE_16);
|
||||
channel_config_set_dreq(&_DMA_Transmit_Channel, i2c_get_dreq(I2C_HARDWARE_UNIT, true));
|
||||
channel_config_set_read_increment(&_DMA_Transmit_Channel, true);
|
||||
channel_config_set_write_increment(&_DMA_Transmit_Channel, false);
|
||||
dma_channel_configure( _DMA_Transmit_Claim,
|
||||
&_DMA_Transmit_Channel,
|
||||
&i2c_get_hw(I2C_HARDWARE_UNIT)->data_cmd, // Write Address
|
||||
NULL, // Read Address
|
||||
0, // Element Count (Each element is of size transfer_data_size)
|
||||
false); // DO NOT start directly
|
||||
|
||||
|
||||
dma_channel_set_irq1_enabled(_DMA_Transmit_Claim, true);
|
||||
|
||||
// Configure the processor to run the ISR when DMA IRQ 0 is asserted
|
||||
irq_set_exclusive_handler(DMA_IRQ_1, ISR_I2C_DMA_Transmit_Complete);
|
||||
irq_set_enabled(DMA_IRQ_1, true);
|
||||
|
||||
_DMA_Transfer_Complete = true;
|
||||
}
|
||||
|
||||
int I2CM_Transmit(uint8_t slave_address, void *data, size_t data_length, bool use_dma, bool nostop)
|
||||
{
|
||||
if(use_dma)
|
||||
{
|
||||
// return 0;
|
||||
if(dma_channel_is_busy(_DMA_Transmit_Claim)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Apply flag for Stop Bit at last Data Set
|
||||
((uint16_t*)data)[data_length-1] |= I2C_IC_DATA_CMD_STOP_BITS;
|
||||
|
||||
dma_channel_set_read_addr (_DMA_Transmit_Claim, (uint16_t*) data , false);
|
||||
dma_channel_set_trans_count (_DMA_Transmit_Claim, data_length , true);
|
||||
}
|
||||
else
|
||||
{
|
||||
return i2c_write_blocking(I2C_HARDWARE_UNIT, slave_address, (uint8_t*)data, data_length, nostop);
|
||||
}
|
||||
}
|
||||
|
||||
int I2CM_Receive(uint8_t slave_address, uint8_t *receive_data, size_t data_length)
|
||||
{
|
||||
return i2c_read_blocking(I2C_HARDWARE_UNIT, slave_address, receive_data, data_length, false);
|
||||
}
|
||||
|
||||
bool I2CM_DMA_Transmit_Complete()
|
||||
{
|
||||
bool Return_Value = _DMA_Transfer_Complete;
|
||||
|
||||
_DMA_Transfer_Complete = false;
|
||||
|
||||
return Return_Value;
|
||||
}
|
||||
|
||||
int I2CM_Packet_Transmit(uint8_t slave_address, uint reg_address, uint8_t address_length, uint8_t *transmit_data, uint8_t data_length)
|
||||
{
|
||||
uint8_t *Transmit_Data = malloc(address_length + data_length);
|
||||
|
||||
for(uint i=0;i<address_length;i++)
|
||||
{
|
||||
Transmit_Data[i] = (uint8_t)(reg_address >> (8*(address_length - i - 1)));
|
||||
}
|
||||
|
||||
for(uint i=0;i<data_length;i++)
|
||||
{
|
||||
Transmit_Data[i + address_length] = transmit_data[i];
|
||||
}
|
||||
|
||||
int status = I2CM_Transmit(slave_address, Transmit_Data, address_length + data_length, false, false);
|
||||
|
||||
free(Transmit_Data);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
// Receive packet from specific slave address
|
||||
int I2CM_Packet_Receive(const uint8_t slave_address, const uint reg_address, const uint8_t address_length, uint8_t *receive_data , const uint8_t data_length)
|
||||
{
|
||||
uint8_t *Address_Data = malloc(address_length);
|
||||
for(uint i=0;i<address_length;i++)
|
||||
{
|
||||
Address_Data[i] = (uint8_t)(reg_address >> (8*(address_length - i - 1)));
|
||||
}
|
||||
|
||||
int status = I2CM_Transmit(slave_address, Address_Data, address_length, false, true);
|
||||
|
||||
return I2CM_Receive(slave_address, receive_data, data_length);
|
||||
}
|
||||
Reference in New Issue
Block a user