From f6a842b1b064c83d42dfd626e888f79e4c1633e8 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Tue, 7 Aug 2018 10:18:25 +0200 Subject: Support optional SoftI2C pullups on MSP430 --- Makefile | 4 +++ include/arch/msp430fr5969lp/driver/gpio.h | 41 +++++++++++++++++++++++++ src/arch/msp430fr5969lp/arch.cc | 7 +++++ src/arch/msp430fr5969lp/driver/i2c.cc | 2 +- src/driver/soft_i2c.cc | 51 +++++++++++++++++++------------ 5 files changed, 85 insertions(+), 20 deletions(-) diff --git a/Makefile b/Makefile index e5dc27d..f6b1f0e 100644 --- a/Makefile +++ b/Makefile @@ -32,6 +32,10 @@ ifneq ($(findstring softi2c,${drivers}), ) COMMON_FLAGS += -DDRIVER_SOFTI2C endif +ifeq (${softi2c_pullup}, 1) + COMMON_FLAGS += -DSOFTI2C_PULLUP +endif + ifeq (${timer_cycles}, 1) COMMON_FLAGS += -DTIMER_CYCLES endif diff --git a/include/arch/msp430fr5969lp/driver/gpio.h b/include/arch/msp430fr5969lp/driver/gpio.h index caed74a..71dab88 100644 --- a/include/arch/msp430fr5969lp/driver/gpio.h +++ b/include/arch/msp430fr5969lp/driver/gpio.h @@ -63,6 +63,29 @@ class GPIO { PJDIR &= ~(1 << (pin - pj_0)); } } + inline void input(unsigned char const pin, unsigned char const pull) { + if (pin < p2_0) { + P1DIR &= ~(1 << pin); + P1OUT = pull ? (P1OUT | (1 << pin)) : (P1OUT & ~(1 << pin)); + P1REN |= (1 << pin); + } else if (pin < p3_0) { + P2DIR &= ~(1 << (pin - p2_0)); + P2OUT = pull ? (P2OUT | (1 << (pin - p2_0))) : (P2OUT & ~(1 << (pin - p2_0))); + P2REN |= (1 << (pin - p2_0)); + } else if (pin < p4_0) { + P3DIR &= ~(1 << (pin - p3_0)); + P3OUT = pull ? (P3OUT | (1 << (pin - p3_0))) : (P3OUT & ~(1 << (pin - p3_0))); + P3REN |= (1 << (pin - p3_0)); + } else if (pin < pj_0) { + P4DIR &= ~(1 << (pin - p4_0)); + P4OUT = pull ? (P4OUT | (1 << (pin - p4_0))) : (P4OUT & ~(1 << (pin - p4_0))); + P4REN |= (1 << (pin - p4_0)); + } else if (pin < PIN_INVALID) { + PJDIR &= ~(1 << (pin - pj_0)); + PJOUT = pull ? (PJOUT | (1 << (pin - pj_0))) : (PJOUT & ~(1 << (pin - pj_0))); + PJREN |= (1 << (pin - pj_0)); + } + } inline void output(unsigned char const pin) { if (pin < p2_0) { P1DIR |= (1 << pin); @@ -76,6 +99,24 @@ class GPIO { PJDIR |= (1 << (pin - pj_0)); } } + inline void output(unsigned char const pin, unsigned char const value) { + if (pin < p2_0) { + P1OUT = value ? (P1OUT | (1 << pin)) : (P1OUT & ~(1 << pin)); + P1DIR |= (1 << pin); + } else if (pin < p3_0) { + P2OUT = value ? (P2OUT | (1 << (pin - p2_0))) : (P2OUT & ~(1 << (pin - p2_0))); + P2DIR |= (1 << (pin - p2_0)); + } else if (pin < p4_0) { + P3OUT = value ? (P3OUT | (1 << (pin - p3_0))) : (P3OUT & ~(1 << (pin - p3_0))); + P3DIR |= (1 << (pin - p3_0)); + } else if (pin < pj_0) { + P4OUT = value ? (P4OUT | (1 << (pin - p4_0))) : (P4OUT & ~(1 << (pin - p4_0))); + P4DIR |= (1 << (pin - p4_0)); + } else if (pin < PIN_INVALID) { + PJOUT = value ? (PJOUT | (1 << (pin - pj_0))) : (PJOUT & ~(1 << (pin - pj_0))); + PJDIR |= (1 << (pin - pj_0)); + } + } inline unsigned char read(unsigned char const pin) { if (pin < p2_0) { return P1IN & (1 << pin); diff --git a/src/arch/msp430fr5969lp/arch.cc b/src/arch/msp430fr5969lp/arch.cc index 9ea49b7..ddb84a4 100644 --- a/src/arch/msp430fr5969lp/arch.cc +++ b/src/arch/msp430fr5969lp/arch.cc @@ -72,6 +72,13 @@ extern void loop(); volatile char run_loop = 0; #endif +void Arch::delay_us(unsigned char const us) +{ + for (int i = 0; i < us/10; i++) { + __delay_cycles(160); + } +} + void Arch::idle_loop(void) { while (1) { diff --git a/src/arch/msp430fr5969lp/driver/i2c.cc b/src/arch/msp430fr5969lp/driver/i2c.cc index fffc28c..55f8591 100644 --- a/src/arch/msp430fr5969lp/driver/i2c.cc +++ b/src/arch/msp430fr5969lp/driver/i2c.cc @@ -16,7 +16,7 @@ signed char I2C::setup() UCB0CTL1 &= ~UCSWRST; UCB0I2CSA = 0; - __delay_cycles(1600); + arch.delay_us(100); if (UCB0STAT & UCBBUSY) return -1; diff --git a/src/driver/soft_i2c.cc b/src/driver/soft_i2c.cc index 94ab261..e7b8548 100644 --- a/src/driver/soft_i2c.cc +++ b/src/driver/soft_i2c.cc @@ -1,32 +1,45 @@ #include "driver/soft_i2c.h" #include "driver/gpio.h" +#include "arch.h" + +#ifdef SOFTI2C_PULLUP +#define SDA_HIGH gpio.input(sda, 1) +#define SDA_LOW gpio.output(sda, 0) +#define SCL_HIGH gpio.input(scl, 1) +#define SCL_LOW gpio.output(scl, 0) +#else +#define SDA_HIGH gpio.input(sda) +#define SDA_LOW gpio.output(sda) +#define SCL_HIGH gpio.input(scl) +#define SCL_LOW gpio.output(scl) +#endif signed char SoftI2C::setup() { - gpio.write(sda, 0); - gpio.write(scl, 0); + SDA_HIGH; + SCL_HIGH; return 0; } void SoftI2C::start() { - gpio.input(sda); - gpio.input(scl); + SDA_HIGH; + SCL_HIGH; // - gpio.output(sda); + SDA_LOW; // - gpio.output(scl); + SCL_LOW; } void SoftI2C::stop() { - gpio.output(scl); + SCL_LOW; // - gpio.output(sda); + SDA_LOW; // - gpio.input(scl); + SCL_HIGH; // - gpio.input(sda); + SDA_HIGH; } bool SoftI2C::tx(unsigned char byte) @@ -34,20 +47,20 @@ bool SoftI2C::tx(unsigned char byte) unsigned char got_ack = 0; for (unsigned char i = 0; i <= 8; i++) { if ((byte & 0x80) || (i == 8)) { - gpio.input(sda); + SDA_HIGH; } else { - gpio.output(sda); + SDA_LOW; } byte <<= 1; // - gpio.input(scl); + SCL_HIGH; // if (i == 8) { if (!gpio.read(sda)) { got_ack = 1; } } - gpio.output(scl); + SCL_LOW; // } return got_ack; @@ -56,21 +69,21 @@ bool SoftI2C::tx(unsigned char byte) unsigned char SoftI2C::rx(bool send_ack) { unsigned char byte = 0; - gpio.input(sda); + SDA_HIGH; for (unsigned char i = 0; i <= 8; i++) { // - gpio.input(scl); + SCL_HIGH; // if ((i < 8) && gpio.read(sda)) { byte |= 1 << (7 - i); } // - gpio.output(scl); + SCL_LOW; // if ((i == 7) && send_ack) { - gpio.output(sda); + SDA_LOW; } else if ((i == 8) && send_ack) { - gpio.input(sda); + SDA_HIGH; } } return byte; -- cgit v1.2.3