- Added function to read out the display_buffer via USB-Serial - Added basic structure and files for later complete firmware (still in progress) - Added Doc folder with schematic in it - Added Python script and batch file to read out the display buffer and open the image in gimp
166 lines
4.8 KiB
C
166 lines
4.8 KiB
C
/*
|
|
* 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);
|
|
|
|
free (Address_Data);
|
|
|
|
if(status < 0) {
|
|
return status;
|
|
}
|
|
|
|
return I2CM_Receive(slave_address, receive_data, data_length);
|
|
} |