From 26bfae58d47ae81b78af965ccc59ca63b6203869 Mon Sep 17 00:00:00 2001 From: Bob-the-Kuhn Date: Tue, 10 Oct 2017 23:52:53 -0500 Subject: [PATCH] MPC4451 I2C support --- Marlin/src/HAL/HAL_LPC1768/include/Wire.h | 58 ++++++ .../include/digipot_mcp4451_I2C_routines.c | 171 ++++++++++++++++++ Marlin/src/HAL/utility/twi.h | 4 + Marlin/src/module/stepper.h | 2 +- 4 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 Marlin/src/HAL/HAL_LPC1768/include/Wire.h create mode 100644 Marlin/src/HAL/HAL_LPC1768/include/digipot_mcp4451_I2C_routines.c create mode 100644 Marlin/src/HAL/utility/twi.h diff --git a/Marlin/src/HAL/HAL_LPC1768/include/Wire.h b/Marlin/src/HAL/HAL_LPC1768/include/Wire.h new file mode 100644 index 0000000000..7e736829b5 --- /dev/null +++ b/Marlin/src/HAL/HAL_LPC1768/include/Wire.h @@ -0,0 +1,58 @@ +/* + TwoWire.h - TWI/I2C library for Arduino & Wiring + 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 + + Modified 2012 by Todd Krein (todd@krein.org) to implement repeated starts +*/ + +// Modified for use with the mcp4451 digipot routine + +#if defined(TARGET_LPC1768) + +#ifndef TwoWire_h +#define TwoWire_h + +#include + +class TwoWire +{ + + public: +// TwoWire(); + void begin(); + void beginTransmission(uint8_t); + uint8_t endTransmission(void); + size_t write(uint8_t); +}; + +//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 diff --git a/Marlin/src/HAL/HAL_LPC1768/include/digipot_mcp4451_I2C_routines.c b/Marlin/src/HAL/HAL_LPC1768/include/digipot_mcp4451_I2C_routines.c new file mode 100644 index 0000000000..6b2372fcd6 --- /dev/null +++ b/Marlin/src/HAL/HAL_LPC1768/include/digipot_mcp4451_I2C_routines.c @@ -0,0 +1,171 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * +*/ + +// adapted from I2C/master/master.c example +// https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html + + + +#if defined(TARGET_LPC1768) + + #ifdef __cplusplus + extern "C" { + #endif + + #include + #include + #include + + ////////////////////////////////////////////////////////////////////////////////////// + + // These two routines are exact copies of the lpc17xx_i2c.c routines. Couldn't link to + // to the lpc17xx_i2c.c routines so had to copy them into this file & rename them. + + static uint32_t _I2C_Start (LPC_I2C_TypeDef *I2Cx) + { + // Reset STA, STO, SI + I2Cx->I2CONCLR = I2C_I2CONCLR_SIC|I2C_I2CONCLR_STOC|I2C_I2CONCLR_STAC; + + // Enter to Master Transmitter mode + I2Cx->I2CONSET = I2C_I2CONSET_STA; + + // Wait for complete + while (!(I2Cx->I2CONSET & I2C_I2CONSET_SI)); + I2Cx->I2CONCLR = I2C_I2CONCLR_STAC; + return (I2Cx->I2STAT & I2C_STAT_CODE_BITMASK); + } + + static void _I2C_Stop (LPC_I2C_TypeDef *I2Cx) + { + + /* Make sure start bit is not active */ + if (I2Cx->I2CONSET & I2C_I2CONSET_STA) + { + I2Cx->I2CONCLR = I2C_I2CONCLR_STAC; + } + + I2Cx->I2CONSET = I2C_I2CONSET_STO|I2C_I2CONSET_AA; + + I2Cx->I2CONCLR = I2C_I2CONCLR_SIC; + } + + + ////////////////////////////////////////////////////////////////////////////////////// + + + #define USEDI2CDEV_M 1 // use I2C1 controller + + #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 + + + PINSEL_CFG_Type PinCfg; + I2C_M_SETUP_Type transferMCfg; + + #define I2C_status (LPC_I2C1->I2STAT & I2C_STAT_CODE_BITMASK) + + + uint8_t digipot_mcp4451_start(uint8_t sla) { // send slave address and write bit + // Sometimes TX data ACK or NAK status is returned. That mean the start state didn't + // happen which means only the value of the slave address was send. Keep looping until + // the slave address and write bit are actually sent. + do{ + _I2C_Stop(I2CDEV_M); // output stop state on I2C bus + _I2C_Start(I2CDEV_M); // output start state on I2C bus + while ((I2C_status != I2C_I2STAT_M_TX_START) + && (I2C_status != I2C_I2STAT_M_TX_RESTART) + && (I2C_status != I2C_I2STAT_M_TX_DAT_ACK) + && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for start to be asserted + + LPC_I2C1->I2CONCLR = I2C_I2CONCLR_STAC; // clear start state before tansmitting slave address + LPC_I2C1->I2DAT = (sla <<1) & I2C_I2DAT_BITMASK; // transmit slave address & write bit + LPC_I2C1->I2CONSET = I2C_I2CONSET_AA; + LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC; + while ((I2C_status != I2C_I2STAT_M_TX_SLAW_ACK) + && (I2C_status != I2C_I2STAT_M_TX_SLAW_NACK) + && (I2C_status != I2C_I2STAT_M_TX_DAT_ACK) + && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); //wait for slaw to finish + }while ( (I2C_status == I2C_I2STAT_M_TX_DAT_ACK) || (I2C_status == I2C_I2STAT_M_TX_DAT_NACK)); + return 1; + } + + + void digipot_mcp4451_init(void) { + + /* + * Init I2C pin connect + */ + 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, 400000); // hardwired to 400KHz bit rate, 100KHz is the other option + + /* Enable Master I2C operation */ + I2C_Cmd(I2CDEV_M, I2C_MASTER_MODE, ENABLE); + } + + + uint8_t digipot_mcp4451_send_byte(uint8_t data) { + + LPC_I2C1->I2DAT = data & I2C_I2DAT_BITMASK; // transmit data + LPC_I2C1->I2CONSET = I2C_I2CONSET_AA; + LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC; + while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK)); // wait for xmit to finish + return 1; + } + + + #ifdef __cplusplus + } + #endif +#endif diff --git a/Marlin/src/HAL/utility/twi.h b/Marlin/src/HAL/utility/twi.h new file mode 100644 index 0000000000..b80776ac40 --- /dev/null +++ b/Marlin/src/HAL/utility/twi.h @@ -0,0 +1,4 @@ +// Modified for use with the mcp4451 digipot routine +#if defined(TARGET_LPC1768) + +#endif diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index c87c4ea1dd..6ea5517364 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -297,7 +297,7 @@ class Stepper { #ifdef CPU_32_BIT // In case of high-performance processor, it is able to calculate in real-time - constexpr uint32_t MIN_TIME_PER_STEP = (HAL_STEPPER_TIMER_RATE) / ((STEP_DOUBLER_FREQUENCY) * 2); + const uint32_t MIN_TIME_PER_STEP = (HAL_STEPPER_TIMER_RATE) / ((STEP_DOUBLER_FREQUENCY) * 2); timer = uint32_t(HAL_STEPPER_TIMER_RATE) / step_rate; NOLESS(timer, MIN_TIME_PER_STEP); // (STEP_DOUBLER_FREQUENCY * 2 kHz - this should never happen) #else