From 6856eccc772b46f2ad38cb7318a32f1e33f5b3a1 Mon Sep 17 00:00:00 2001 From: Thomas Moore Date: Thu, 9 Nov 2017 21:46:26 -0600 Subject: [PATCH] Master-only TwoWire class for LPC1768 --- Marlin/src/HAL/HAL_LPC1768/Wire.cpp | 238 ++++++++++++++++++++++ Marlin/src/HAL/HAL_LPC1768/include/Wire.h | 62 +++--- Marlin/src/feature/I2CPositionEncoder.cpp | 1 + 3 files changed, 275 insertions(+), 26 deletions(-) create mode 100644 Marlin/src/HAL/HAL_LPC1768/Wire.cpp diff --git a/Marlin/src/HAL/HAL_LPC1768/Wire.cpp b/Marlin/src/HAL/HAL_LPC1768/Wire.cpp new file mode 100644 index 0000000000..2229062893 --- /dev/null +++ b/Marlin/src/HAL/HAL_LPC1768/Wire.cpp @@ -0,0 +1,238 @@ +/* + TwoWire.cpp - TWI/I2C library for Wiring & Arduino + Copyright (c) 2006 Nicholas Zambetti. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifdef TARGET_LPC1768 + +extern "C" { + #include + #include + #include + #include + #include + #include +} + +#include "Wire.h" + +#define USEDI2CDEV_M 1 + +#if (USEDI2CDEV_M == 0) + #define I2CDEV_M LPC_I2C0 +#elif (USEDI2CDEV_M == 1) + #define I2CDEV_M LPC_I2C1 +#elif (USEDI2CDEV_M == 2) + #define I2CDEV_M LPC_I2C2 +#else + #error "Master I2C device not defined!" +#endif + +// Initialize Class Variables ////////////////////////////////////////////////// + +uint8_t TwoWire::rxBuffer[BUFFER_LENGTH]; +uint8_t TwoWire::rxBufferIndex = 0; +uint8_t TwoWire::rxBufferLength = 0; + +uint8_t TwoWire::txAddress = 0; +uint8_t TwoWire::txBuffer[BUFFER_LENGTH]; +uint8_t TwoWire::txBufferIndex = 0; +uint8_t TwoWire::txBufferLength = 0; + +uint8_t TwoWire::transmitting = 0; + +// Constructors //////////////////////////////////////////////////////////////// + +TwoWire::TwoWire() { +} + +// Public Methods ////////////////////////////////////////////////////////////// + +void TwoWire::begin(void) { + rxBufferIndex = 0; + rxBufferLength = 0; + + txBufferIndex = 0; + txBufferLength = 0; + + /* + * Init I2C pin connect + */ + PINSEL_CFG_Type PinCfg; + PinCfg.OpenDrain = 0; + PinCfg.Pinmode = 0; + #if ((USEDI2CDEV_M == 0)) + PinCfg.Funcnum = 1; + PinCfg.Pinnum = 27; + PinCfg.Portnum = 0; + PINSEL_ConfigPin(&PinCfg); // SDA0 / D57 AUX-1 + PinCfg.Pinnum = 28; + PINSEL_ConfigPin(&PinCfg); // SCL0 / D58 AUX-1 + #endif + #if ((USEDI2CDEV_M == 1)) + PinCfg.Funcnum = 3; + PinCfg.Pinnum = 0; + PinCfg.Portnum = 0; + PINSEL_ConfigPin(&PinCfg); // SDA1 / D20 SCA + PinCfg.Pinnum = 1; + PINSEL_ConfigPin(&PinCfg); // SCL1 / D21 SCL + #endif + #if ((USEDI2CDEV_M == 2)) + PinCfg.Funcnum = 2; + PinCfg.Pinnum = 10; + PinCfg.Portnum = 0; + PINSEL_ConfigPin(&PinCfg); // SDA2 / D38 X_ENABLE_PIN + PinCfg.Pinnum = 11; + PINSEL_ConfigPin(&PinCfg); // SCL2 / D55 X_DIR_PIN + #endif + + // Initialize I2C peripheral + I2C_Init(I2CDEV_M, 100000); + + // Enable Master I2C operation + I2C_Cmd(I2CDEV_M, I2C_MASTER_MODE, ENABLE); +} + +uint8_t TwoWire::requestFrom(uint8_t address, uint8_t quantity) { + // clamp to buffer length + if(quantity > BUFFER_LENGTH){ + quantity = BUFFER_LENGTH; + } + + // perform blocking read into buffer + I2C_M_SETUP_Type transferMCfg; + transferMCfg.sl_addr7bit = address >> 1; // not sure about the right shift + transferMCfg.tx_data = NULL; + transferMCfg.tx_length = 0; + transferMCfg.rx_data = rxBuffer; + transferMCfg.rx_length = quantity; + transferMCfg.retransmissions_max = 3; + I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING); + + // set rx buffer iterator vars + rxBufferIndex = 0; + rxBufferLength = transferMCfg.rx_count; + + return transferMCfg.rx_count; +} + +uint8_t TwoWire::requestFrom(int address, int quantity) { + return requestFrom((uint8_t)address, (uint8_t)quantity); +} + +void TwoWire::beginTransmission(uint8_t address) { + // indicate that we are transmitting + transmitting = 1; + // set address of targeted slave + txAddress = address; + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; +} + +void TwoWire::beginTransmission(int address) { + beginTransmission((uint8_t)address); +} + +uint8_t TwoWire::endTransmission(void) { + // transmit buffer (blocking) + I2C_M_SETUP_Type transferMCfg; + transferMCfg.sl_addr7bit = txAddress >> 1; // not sure about the right shift + transferMCfg.tx_data = txBuffer; + transferMCfg.tx_length = txBufferLength; + transferMCfg.rx_data = NULL; + transferMCfg.rx_length = 0; + transferMCfg.retransmissions_max = 3; + Status status = I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING); + + // reset tx buffer iterator vars + txBufferIndex = 0; + txBufferLength = 0; + + // indicate that we are done transmitting + transmitting = 0; + + if (status == SUCCESS) + return 0; // success + else + return 4; // other error +} + +// must be called after beginTransmission(address) +size_t TwoWire::write(uint8_t data) { + if (transmitting) { + // don't bother if buffer is full + if (txBufferLength >= BUFFER_LENGTH) { + return 0; + } + + // put byte in tx buffer + txBuffer[txBufferIndex] = data; + ++txBufferIndex; + + // update amount in buffer + txBufferLength = txBufferIndex; + } + + return 1; +} + +// must be called after beginTransmission(address) +size_t TwoWire::write(const uint8_t *data, size_t quantity) { + size_t sent = 0; + if (transmitting) + for(sent = 0; sent < quantity; ++sent) + if (!write(data[sent])) + break; + + return sent; +} + +// must be called after requestFrom(address, numBytes) +int TwoWire::available(void) { + return rxBufferLength - rxBufferIndex; +} + +// must be called after requestFrom(address, numBytes) +int TwoWire::read(void) { + int value = -1; + + // get each successive byte on each call + if(rxBufferIndex < rxBufferLength) { + value = rxBuffer[rxBufferIndex]; + ++rxBufferIndex; + } + + return value; +} + +// must be called after requestFrom(address, numBytes) +int TwoWire::peek(void) { + int value = -1; + + if(rxBufferIndex < rxBufferLength){ + value = rxBuffer[rxBufferIndex]; + } + + return value; +} + +// Preinstantiate Objects ////////////////////////////////////////////////////// + +TwoWire Wire = TwoWire(); + +#endif // TARGET_LPC1768 \ No newline at end of file diff --git a/Marlin/src/HAL/HAL_LPC1768/include/Wire.h b/Marlin/src/HAL/HAL_LPC1768/include/Wire.h index 491894b659..5c4b0b9518 100644 --- a/Marlin/src/HAL/HAL_LPC1768/include/Wire.h +++ b/Marlin/src/HAL/HAL_LPC1768/include/Wire.h @@ -1,4 +1,4 @@ -/* +/** * TwoWire.h - TWI/I2C library for Arduino & Wiring * Copyright (c) 2006 Nicholas Zambetti. All right reserved. * @@ -19,39 +19,49 @@ * Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts */ -// Modified for use with the mcp4451 digipot routine - -#ifdef TARGET_LPC1768 - -#ifndef TwoWire_h -#define TwoWire_h +#ifndef _TWOWIRE_H_ +#define _TWOWIRE_H_ #include +#define BUFFER_LENGTH 32 + class TwoWire { + private: + static uint8_t rxBuffer[]; + static uint8_t rxBufferIndex; + static uint8_t rxBufferLength; + + static uint8_t txAddress; + static uint8_t txBuffer[]; + static uint8_t txBufferIndex; + static uint8_t txBufferLength; + + static uint8_t transmitting; + public: - //TwoWire(); + TwoWire(); void begin(); void beginTransmission(uint8_t); + void beginTransmission(int); uint8_t endTransmission(void); - size_t write(uint8_t); + uint8_t endTransmission(uint8_t); + + uint8_t requestFrom(uint8_t, uint8_t); + uint8_t requestFrom(int, int); + + virtual size_t write(uint8_t); + virtual size_t write(const uint8_t *, size_t); + virtual int available(void); + virtual int read(void); + virtual int peek(void); + + inline size_t write(unsigned long n) { return write((uint8_t)n); } + inline size_t write(long n) { return write((uint8_t)n); } + inline size_t write(unsigned int n) { return write((uint8_t)n); } + inline size_t write(int n) { return write((uint8_t)n); } }; -//extern TwoWire Wire; +extern TwoWire Wire; -TwoWire Wire; - -//////////////////////////////////////////////////////////////////////////////////////// - -extern "C" uint8_t digipot_mcp4451_start(uint8_t sla); -extern "C" void digipot_mcp4451_init(void); -extern "C" uint8_t digipot_mcp4451_send_byte(uint8_t data); - - -void TwoWire::beginTransmission(uint8_t sla) { digipot_mcp4451_start(sla);} -void TwoWire::begin(void) {digipot_mcp4451_init();} -size_t TwoWire::write(uint8_t data) {return digipot_mcp4451_send_byte(data);} -uint8_t TwoWire::endTransmission(void) {return 1;} - -#endif -#endif // TARGET_LPC1768 +#endif // _TWOWIRE_H_ diff --git a/Marlin/src/feature/I2CPositionEncoder.cpp b/Marlin/src/feature/I2CPositionEncoder.cpp index bf4c3676df..28da22fa96 100644 --- a/Marlin/src/feature/I2CPositionEncoder.cpp +++ b/Marlin/src/feature/I2CPositionEncoder.cpp @@ -37,6 +37,7 @@ #include "../module/temperature.h" #include "../module/stepper.h" #include "../gcode/parser.h" +#include "binary.h" #include