mirror of
https://github.com/supleed2/EIE4-FYP.git
synced 2024-12-22 14:15:50 +00:00
Add amp control library using i2c
This commit is contained in:
parent
cd0defbbb4
commit
44215ffdf0
|
@ -3,7 +3,7 @@ BUILD_DIR?=../build/gsd_orangecrab/
|
||||||
include $(BUILD_DIR)/software/include/generated/variables.mak
|
include $(BUILD_DIR)/software/include/generated/variables.mak
|
||||||
include $(SOC_DIRECTORY)/software/common.mak
|
include $(SOC_DIRECTORY)/software/common.mak
|
||||||
|
|
||||||
OBJECTS = audio.o can.o crt0.o donut.o isr.o led.o main.o
|
OBJECTS = amp.o audio.o can.o crt0.o donut.o isr.o led.o main.o
|
||||||
CFLAGS += -DWITH_CXX
|
CFLAGS += -DWITH_CXX
|
||||||
|
|
||||||
|
|
||||||
|
|
33
demo/amp
Normal file
33
demo/amp
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#include <generated/csr.h>
|
||||||
|
#include <libbase/i2c.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Struct Definition
|
||||||
|
|
||||||
|
struct amp_i2c {
|
||||||
|
uint8_t pot0;
|
||||||
|
uint8_t pot1;
|
||||||
|
uint8_t conf;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function Declarations
|
||||||
|
|
||||||
|
bool amp_init(void);
|
||||||
|
|
||||||
|
bool amp_read(amp_i2c &);
|
||||||
|
|
||||||
|
bool amp_read_pot0(uint8_t &);
|
||||||
|
|
||||||
|
bool amp_read_pot1(uint8_t &);
|
||||||
|
|
||||||
|
bool amp_read_conf(uint8_t &);
|
||||||
|
|
||||||
|
bool amp_write(amp_i2c value);
|
||||||
|
|
||||||
|
bool amp_write_pot0(uint8_t value);
|
||||||
|
|
||||||
|
bool amp_write_pot1(uint8_t value);
|
||||||
|
|
||||||
|
bool amp_write_conf(uint8_t value);
|
178
demo/amp.cpp
Normal file
178
demo/amp.cpp
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
#include "amp"
|
||||||
|
#include <generated/csr.h>
|
||||||
|
#include <libbase/i2c.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef CONFIG_HAS_I2C
|
||||||
|
#define I2C_DELAY(n) busy_wait_us(n * (250000 / I2C_FREQ_HZ))
|
||||||
|
|
||||||
|
static inline void i2c_oe_scl_sda(bool oe, bool scl, bool sda) {
|
||||||
|
i2c_w_write(
|
||||||
|
((oe & 1) << CSR_I2C_W_OE_OFFSET) |
|
||||||
|
((scl & 1) << CSR_I2C_W_SCL_OFFSET) |
|
||||||
|
((sda & 1) << CSR_I2C_W_SDA_OFFSET));
|
||||||
|
}
|
||||||
|
|
||||||
|
// START condition: 1-to-0 transition of SDA when SCL is 1
|
||||||
|
static void i2c_start(void) {
|
||||||
|
i2c_oe_scl_sda(1, 1, 1);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(1, 1, 0);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(1, 0, 0);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// STOP condition: 0-to-1 transition of SDA when SCL is 1
|
||||||
|
static void i2c_stop(void) {
|
||||||
|
i2c_oe_scl_sda(1, 0, 0);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(1, 1, 0);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(1, 1, 1);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(0, 1, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call when in the middle of SCL low, advances one clk period
|
||||||
|
static void i2c_transmit_bit(int value) {
|
||||||
|
i2c_oe_scl_sda(1, 0, value);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(1, 1, value);
|
||||||
|
I2C_DELAY(2);
|
||||||
|
i2c_oe_scl_sda(1, 0, value);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call when in the middle of SCL low, advances one clk period
|
||||||
|
static int i2c_receive_bit(void) {
|
||||||
|
int value;
|
||||||
|
i2c_oe_scl_sda(0, 0, 0);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(0, 1, 0);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
// read in the middle of SCL high
|
||||||
|
value = i2c_r_read() & 1;
|
||||||
|
I2C_DELAY(1);
|
||||||
|
i2c_oe_scl_sda(0, 0, 0);
|
||||||
|
I2C_DELAY(1);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send data byte and return 1 if slave sends ACK
|
||||||
|
static bool i2c_transmit_byte(unsigned char data) {
|
||||||
|
int i;
|
||||||
|
int ack;
|
||||||
|
|
||||||
|
// SCL should have already been low for 1/4 cycle
|
||||||
|
// Keep SDA low to avoid short spikes from the pull-ups
|
||||||
|
i2c_oe_scl_sda(1, 0, 0);
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
// MSB first
|
||||||
|
i2c_transmit_bit((data & (1 << 7)) != 0);
|
||||||
|
data <<= 1;
|
||||||
|
}
|
||||||
|
i2c_oe_scl_sda(0, 0, 0); // release line
|
||||||
|
ack = i2c_receive_bit();
|
||||||
|
|
||||||
|
// 0 from slave means ack
|
||||||
|
return ack == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read data byte and send ACK if ack=1
|
||||||
|
static unsigned char i2c_receive_byte(bool ack) {
|
||||||
|
int i;
|
||||||
|
unsigned char data = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < 8; ++i) {
|
||||||
|
data <<= 1;
|
||||||
|
data |= i2c_receive_bit();
|
||||||
|
}
|
||||||
|
i2c_transmit_bit(!ack);
|
||||||
|
i2c_oe_scl_sda(0, 0, 0); // release line
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_init(void) {
|
||||||
|
return amp_write({0x00, 0x00, 0x07});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_read(amp_i2c &rcv) {
|
||||||
|
i2c_start();
|
||||||
|
if (!i2c_transmit_byte(I2C_ADDR_RD(0x28))) {
|
||||||
|
i2c_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
rcv.pot0 = i2c_receive_byte(true) & 0x3F;
|
||||||
|
rcv.pot1 = i2c_receive_byte(true) & 0x3F;
|
||||||
|
rcv.conf = i2c_receive_byte(false) & 0x3F;
|
||||||
|
i2c_stop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_read_pot0(uint8_t &pot0) {
|
||||||
|
amp_i2c temp;
|
||||||
|
bool success = amp_read(temp);
|
||||||
|
pot0 = temp.pot0;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_read_pot1(uint8_t &pot1) {
|
||||||
|
amp_i2c temp;
|
||||||
|
bool success = amp_read(temp);
|
||||||
|
pot1 = temp.pot1;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_read_conf(uint8_t &conf) {
|
||||||
|
amp_i2c temp;
|
||||||
|
bool success = amp_read(temp);
|
||||||
|
conf = temp.conf;
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_write(amp_i2c value) {
|
||||||
|
i2c_start();
|
||||||
|
if (!i2c_transmit_byte(I2C_ADDR_WR(0x28))) {
|
||||||
|
i2c_stop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!i2c_transmit_byte(value.pot0)) {
|
||||||
|
i2c_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!i2c_transmit_byte(value.pot1 | 0x40)) {
|
||||||
|
i2c_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!i2c_transmit_byte(value.conf | 0x80)) {
|
||||||
|
i2c_stop();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
i2c_stop();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_write_pot0(uint8_t value) {
|
||||||
|
amp_i2c temp;
|
||||||
|
bool success = amp_read(temp);
|
||||||
|
temp.pot0 = value;
|
||||||
|
return success & amp_write(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_write_pot1(uint8_t value) {
|
||||||
|
amp_i2c temp;
|
||||||
|
bool success = amp_read(temp);
|
||||||
|
temp.pot1 = value;
|
||||||
|
return success & amp_write(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool amp_write_conf(uint8_t value) {
|
||||||
|
amp_i2c temp;
|
||||||
|
bool success = amp_read(temp);
|
||||||
|
temp.conf = value;
|
||||||
|
return success & amp_write(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue