Initial commit: MT firmware project

- BLE peripheral applications
- dr_piezo and bladder_patch projects

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Charles Kwon
2026-01-25 17:26:39 +09:00
commit 72f5eb3cd9
2559 changed files with 1594625 additions and 0 deletions

View File

@@ -0,0 +1,513 @@
/*******************************************************************************
* @file mcp4725_i2c.c
* @author CandyPops Co.
* @version V1.0.0
* @date 2022-09-05
* @brief
******************************************************************************/
/* board driver */
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdbool.h>
#include <math.h>
#include "nrf.h"
#include "app_error.h"
#include "boards.h"
#include "nrfx_gpiote.h"
#include "mcp4725_i2c.h"
#include "nrf_delay.h"
#include "debug_print.h"
/* I2C number and slave address for MCP4725 */
#define MCP4725_I2C_ADDR_7bit 0x66
uint8_t MCP4725_I2C_ADDR = MCP4725_I2C_ADDR_7bit << 1;
uint16_t _lastValue;
uint8_t _powerDownMode;
uint32_t _lastWriteEEPROM;
void mcp4725_i2c_initialize(void)
{
SCL_OUT();
SDA_OUT();
SCL_H();
SDA_H();
}
static uint8_t mcp4725_i2c_write(uint8_t data)
{
for(uint8_t i = 0; i < 8; i++)
{
// MSB first
if(data & 0x80) SDA_H();
else SDA_L();
i2c_clock();
data = data << 1;
}
// read ACK
SDA_H(); // leave SDA HI
SDA_IN(); // change direction to input on SDA line
i2c_delay();
SCL_H(); // clock back up
i2c_delay();
uint8_t ack = SDA_READ(); // get the ACK bit
SCL_L();
SDA_OUT(); // change direction back to output
if(ack) {
DBG_PRINTF("ACK Extra=%d,Data=%d\r\n", ack,data);
}
return ack;
}
static uint8_t mcp4725_i2c_read(bool ack)
{
uint8_t data;
SDA_H(); // leave SDA HI
SDA_IN(); // change direction to input on SDA line
data = 0;
for(uint8_t i = 0; i < 8; i++)
{
// MSB first
data = data << 1;
SCL_H();
do{
}while(SCL_READ() != 0); // Wait for any SCL clock stratching
i2c_delay();
if(SDA_READ()) // get the Data bit
data |= 1;
else
data |= 0;
SCL_L(); // clock LO
i2c_delay();
}
SDA_OUT(); // change direction back to output
// send ACK
if(ack == ACK) SDA_L();
else if(ack == NACK) SDA_H();
i2c_clock();
SDA_H(); // leave with SDA HI
return data;
}
void mcp4725_writeFastMode(const uint16_t value)
{
uint8_t low = value & 0xFF;
uint8_t high = ((value >> 8) & 0x0F); // set C2,c1 == 0,0(FastMode Write) pd1,pd0 == 0,0 (Normal Mode)
i2c_start();
mcp4725_i2c_write(MCP4725_I2C_ADDR|TWI_WRITE); // slave address
//uint8_t address = MCP4725_I2C_ADDR | TWI_WRITE;
//DBG_PRINTF("[I2C] Write to 0x%02X\r\n", address); //oxCC
mcp4725_i2c_write(high); // value1 ~ 3
mcp4725_i2c_write(low);
i2c_stop();
}
void mcp4725_generalCall(const uint8_t gc)
{
i2c_start();
mcp4725_i2c_write(0x00); // First Byte 0x00
mcp4725_i2c_write(gc); // Second Byte, General Call Reset = 0x06, General Call Wake-Up = 0x09
i2c_stop();
}
void mcp4725_init(void)
{
mcp4725_i2c_initialize();
}
// DAC value is reset to EEPROM value
// need to reflect this in cached value
void mcp4725_powerOnReset(void)
{
mcp4725_generalCall(MCP4725_GC_RESET);
}
// _powerDownMode DAC resets to 0 -- PDM EEPROM stays same !!!
// need to reflect this in cached value
void mcp4725_powerOnWakeUp(void)
{
mcp4725_generalCall(MCP4725_GC_WAKEUP);
}
/* 현재 DAC값 읽어서 그 값에 Power Down 넣고 Write */
void mcp4725_PowerDownMode(void)
{
uint8_t low = 0x00; //read_value & 0xFF;
uint8_t high = 0x00; //((read_value >> 8) & 0x0F);
high = high | (MCP4725_PDMODE_1K << 4); // set C2,c1 == 0,0(FastMode Write) pd1,pd0 == 0,1 (Power Down Mode, 1Kohm to GND)
i2c_start();
mcp4725_i2c_write(MCP4725_I2C_ADDR|TWI_WRITE); // slave address
mcp4725_i2c_write(high); // value
mcp4725_i2c_write(low);
i2c_stop();
}
////////////////////////////////////////////////////////////////////////////////
uint16_t mcp4725_readDAC(void)
{
while(!mcp4725_ready());
uint8_t buffer[3];
mcp4725_readRegister(buffer, 3);
uint16_t value = buffer[1];
value = value << 4;
value = value + (buffer[2] >> 4);
return value;
}
// ready checks if the last write to EEPROM has been written.
// until ready all writes to the MCP4725 are ignored!
bool mcp4725_ready(void)
{
uint8_t buffer[1];
mcp4725_readRegister(buffer, 1);
return ((buffer[0] & 0x80) > 0);
}
void mcp4725_writeRegisterMode(const uint16_t value, uint8_t reg)
{
uint8_t high = (value / 16);
uint8_t low = (value & 0x0F) << 4;
reg = reg | (_powerDownMode << 1);
i2c_start();
mcp4725_i2c_write(MCP4725_I2C_ADDR|TWI_WRITE); // slave address
mcp4725_i2c_write(reg); // configuration
mcp4725_i2c_write(high); // value1 ~ 3
mcp4725_i2c_write(low);
i2c_stop();
}
void mcp4725_readRegister(uint8_t* buffer, const uint8_t length)
{
i2c_start();
mcp4725_i2c_write(MCP4725_I2C_ADDR|TWI_READ); // slave address with READ
switch(length) {
case 1:
buffer[0] = mcp4725_i2c_read(NACK); // NACK, SDA = 1;
break;
case 2:
buffer[0] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[1] = mcp4725_i2c_read(NACK); // NACK, SDA = 1;
break;
case 3:
buffer[0] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[1] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[2] = mcp4725_i2c_read(NACK); // NACK, SDA = 1;
break;
case 4:
buffer[0] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[1] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[2] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[3] = mcp4725_i2c_read(NACK); // NACK, SDA = 1;
break;
case 5:
buffer[0] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[1] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[2] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[3] = mcp4725_i2c_read(ACK); // ACK, SDA = 0;
buffer[4] = mcp4725_i2c_read(NACK); // NACK, SDA = 1;
break;
default:
#if FEATURE_PRINTF
DBG_PRINTF("ERR!! mcp4725_i2c_readregister\r\n");
#endif
break;
}
i2c_stop();
}
void mcp4725_setValue(const uint16_t value)
{
if (value == _lastValue) return;
if (value > MCP4725_MAXVALUE) return;
mcp4725_writeFastMode(value);
_lastValue = value;
}
uint16_t mcp4725_getValue(void)
{
return _lastValue;
}
void mcp4725_setPercentage(float percentage)
{
if ((percentage > 100) || (percentage < 0))
DBG_PRINTF("ERR!!! mcp4725 percentage error\r\n");
mcp4725_setValue(round(percentage * (0.01 * MCP4725_MAXVALUE)));
}
// unfortunately it is not possible to write a different value
// to the DAC and EEPROM simultaneously or write EEPROM only.
void mcp4725_writeDAC(const uint16_t value, const bool EEPROM)
{
if (value > MCP4725_MAXVALUE)
#if FEATURE_PRINTF
DBG_PRINTF("ERR!!! mcp4725 writeDAC error\r\n");
#endif
while(!mcp4725_ready());
mcp4725_writeRegisterMode(value, EEPROM ? MCP4725_DACEEPROM : MCP4725_DAC);
_lastValue = value;
}
uint16_t mcp4725_readEEPROM(void)
{
while(!mcp4725_ready());
uint8_t buffer[5];
mcp4725_readRegister(buffer, 5);
uint16_t value = buffer[3] & 0x0F;
value = value << 8;
value = value + buffer[4];
return value;
}
// depending on bool EEPROM the value of PDM is written to
// (false) DAC or
// (true) DAC & EEPROM,
void mcp4725_writePowerDownMode(const uint8_t PDM, const bool EEPROM)
{
_powerDownMode = (PDM & 0x03); // mask PDM bits only (written later low level)
_lastValue = mcp4725_readDAC();
_powerDownMode = mcp4725_readPowerDownModeDAC();
mcp4725_writeDAC(_lastValue, EEPROM);
}
uint8_t mcp4725_readPowerDownModeEEPROM(void)
{
while(!mcp4725_ready());
uint8_t buffer[4];
mcp4725_readRegister(buffer, 4);
uint8_t value = (buffer[3] >> 5) & 0x03;
return value;
}
uint8_t mcp4725_readPowerDownModeDAC(void)
{
while(!mcp4725_ready()); // TODO needed?
uint8_t buffer[1];
mcp4725_readRegister(buffer, 1);
uint8_t value = (buffer[0] >> 1) & 0x03;
return value;
}
void ds_i2c_start(void) {
SDA_H();//nrf_gpio_pin_set(I2C_SDA_PIN);
SCL_H();//nrf_gpio_pin_set(I2C_SCL_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SDA_L();//nrf_gpio_pin_clear(I2C_SDA_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SCL_L();//nrf_gpio_pin_clear(I2C_SCL_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
}
void ds_i2c_stop(void) {
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SDA_L();//nrf_gpio_pin_clear(I2C_SDA_PIN);
SCL_H();// nrf_gpio_pin_set(I2C_SCL_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SDA_H();//nrf_gpio_pin_set(I2C_SDA_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
}
void i2c_write_bit(uint8_t bit) {
if (bit) {
SDA_H();
} else {
SDA_L();
}
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SCL_H(); //nrf_gpio_pin_set(SCL_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SCL_L();//nrf_gpio_pin_clear(SCL_PIN);
}
uint8_t i2c_read_bit(void) {
uint8_t bit;
SDA_IN();//nrf_gpio_cfg_input(SDA_PIN, NRF_GPIO_PIN_NOPULL);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SCL_H(); ////nrf_gpio_pin_set(SCL_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
bit = SDA_READ();//nrf_gpio_pin_read(SDA_PIN);
SCL_L(); //nrf_gpio_pin_clear(SCL_PIN);
SDA_OUT();//nrf_gpio_cfg_output(SDA_PIN);
return bit;
}
uint8_t i2c_write_byte(uint8_t byte) {
for (uint8_t i = 0; i < 8; i++) {
i2c_write_bit(byte & 0x80);
byte <<= 1;
}
return i2c_read_bit(); // Read ACK/NACK
}
uint8_t i2c_read_byte(uint8_t ack) {
uint8_t byte = 0;
SDA_IN();//nrf_gpio_cfg_input(SDA_PIN, NRF_GPIO_PIN_NOPULL);
for (uint8_t i = 0; i < 8; i++) {
byte <<= 1;
byte |= i2c_read_bit();
}
SDA_OUT();//nrf_gpio_cfg_output(SDA_PIN);
i2c_write_bit(!ack); // Send ACK/NACK
return byte;
}
void i2c_repeated_start(void) {
SDA_H();//nrf_gpio_pin_set(SDA_PIN);
SCL_H();//nrf_gpio_pin_set(SCL_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SDA_L();////nrf_gpio_pin_clear(SDA_PIN);
i2c_delay();//nrf_delay_us(I2C_DELAY_US);
SCL_L();//nrf_gpio_pin_clear(SCL_PIN);
}
// i2c_start();
// i2c_write_byte(I2C_ADDRESS << 1); // Write address
// i2c_write_byte(0x00); // Register address
// i2c_write_byte(0xFF); // Data
// i2c_stop();
// // Read example
// i2c_start();
// i2c_write_byte((I2C_ADDRESS << 1) | 1); // Read address
// uint8_t data = i2c_read_byte(0); // Read data with NACK
// i2c_stop();
void DS3930_write(uint8_t id, uint8_t addr, uint8_t wdata)
{
//i2c_start();
// ds_i2c_stop();
ds_i2c_start();
i2c_write_byte(id << 1); // Write address
i2c_write_byte(addr); // Register address
i2c_write_byte(wdata); // Data
// mcp4725_i2c_write(id << 1);
// mcp4725_i2c_write(addr);
// mcp4725_i2c_write(wdata);
//
// }
//i2c_delay();
//i2c_stop();
ds_i2c_stop();
}
uint8_t DS3930_read(uint8_t id, uint8_t addr, uint8_t* rdata)
{
ds_i2c_start();
i2c_write_byte(id << 1); // Write address
i2c_write_byte(addr); // Register address
i2c_repeated_start();
i2c_write_byte((id << 1) | 1); // Read address
uint8_t data = i2c_read_byte(0); // Read data with NACK
ds_i2c_stop();
rdata[0] = data;
DBG_PRINTF("Data 0x%x . \r\n", data);
//i2c_stop();
return data;
}
//void CAT24_write(uint8_t id, uint8_t addr, uint8_t* wdata)
//{
////i2c_start();
//// ds_i2c_stop();
// ds_i2c_start();
// i2c_write_byte(id << 1); // Write address
// i2c_write_byte(addr); // Register address
// i2c_write_byte(wdata); // Data
//
//// mcp4725_i2c_write(id << 1);
//// mcp4725_i2c_write(addr);
//// mcp4725_i2c_write(wdata);
////
//// }
////i2c_delay();
////i2c_stop();
// ds_i2c_stop();
//}
//uint8_t CAT24_read(uint8_t id, uint8_t addr, uint8_t* rdata,uint8_t length)
//{
// ds_i2c_start();
// i2c_write_byte(id << 1); // Write address
// i2c_write_byte(addr); // Register address
// i2c_repeated_start();
// i2c_write_byte((id << 1) | 1); // Read address
// uint8_t data = i2c_read_byte(0); // Read data with NACK
// ds_i2c_stop();
// rdata[0] = data;
// DBG_PRINTF("Data 0x%x . \r\n", data);
// //i2c_stop();
// return data;
//}