diff options
Diffstat (limited to 'Marlin/src/libs/BL24CXX.cpp')
-rw-r--r-- | Marlin/src/libs/BL24CXX.cpp | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/Marlin/src/libs/BL24CXX.cpp b/Marlin/src/libs/BL24CXX.cpp new file mode 100644 index 0000000..8de320d --- /dev/null +++ b/Marlin/src/libs/BL24CXX.cpp @@ -0,0 +1,272 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * 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 <https://www.gnu.org/licenses/>. + * + */ + +#include "../inc/MarlinConfig.h" + +#if ENABLED(IIC_BL24CXX_EEPROM) + +/** + * PersistentStore for Arduino-style EEPROM interface + * with simple implementations supplied by Marlin. + */ + +#include "BL24CXX.h" +#include <libmaple/gpio.h> + +#ifndef EEPROM_WRITE_DELAY + #define EEPROM_WRITE_DELAY 10 +#endif +#ifndef EEPROM_DEVICE_ADDRESS + #define EEPROM_DEVICE_ADDRESS (0x50 << 1) +#endif + +// IO direction setting +#define SDA_IN() do{ PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH &= 0XFFFF0FFF; PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH |= 8 << 12; }while(0) +#define SDA_OUT() do{ PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH &= 0XFFFF0FFF; PIN_MAP[IIC_EEPROM_SDA].gpio_device->regs->CRH |= 3 << 12; }while(0) + +// IO ops +#define IIC_SCL_0() WRITE(IIC_EEPROM_SCL, LOW) +#define IIC_SCL_1() WRITE(IIC_EEPROM_SCL, HIGH) +#define IIC_SDA_0() WRITE(IIC_EEPROM_SDA, LOW) +#define IIC_SDA_1() WRITE(IIC_EEPROM_SDA, HIGH) +#define READ_SDA() READ(IIC_EEPROM_SDA) + +// +// Simple IIC interface via libmaple +// + +// Initialize IIC +void IIC::init() { + SET_OUTPUT(IIC_EEPROM_SDA); + SET_OUTPUT(IIC_EEPROM_SCL); + IIC_SCL_1(); + IIC_SDA_1(); +} + +// Generate IIC start signal +void IIC::start() { + SDA_OUT(); // SDA line output + IIC_SDA_1(); + IIC_SCL_1(); + delay_us(4); + IIC_SDA_0(); // START:when CLK is high, DATA change from high to low + delay_us(4); + IIC_SCL_0(); // Clamp the I2C bus, ready to send or receive data +} + +// Generate IIC stop signal +void IIC::stop() { + SDA_OUT(); // SDA line output + IIC_SCL_0(); + IIC_SDA_0(); // STOP:when CLK is high DATA change from low to high + delay_us(4); + IIC_SCL_1(); + IIC_SDA_1(); // Send I2C bus end signal + delay_us(4); +} + +// Wait for the response signal to arrive +// 1 = failed to receive response +// 0 = response received +uint8_t IIC::wait_ack() { + uint8_t ucErrTime = 0; + SDA_IN(); // SDA is set as input + IIC_SDA_1(); delay_us(1); + IIC_SCL_1(); delay_us(1); + while (READ_SDA()) { + if (++ucErrTime > 250) { + stop(); + return 1; + } + } + IIC_SCL_0(); // Clock output 0 + return 0; +} + +// Generate ACK response +void IIC::ack() { + IIC_SCL_0(); + SDA_OUT(); + IIC_SDA_0(); + delay_us(2); + IIC_SCL_1(); + delay_us(2); + IIC_SCL_0(); +} + +// No ACK response +void IIC::nAck() { + IIC_SCL_0(); + SDA_OUT(); + IIC_SDA_1(); + delay_us(2); + IIC_SCL_1(); + delay_us(2); + IIC_SCL_0(); +} + +// Send one IIC byte +// Return whether the slave responds +// 1 = there is a response +// 0 = no response +void IIC::send_byte(uint8_t txd) { + SDA_OUT(); + IIC_SCL_0(); // Pull down the clock to start data transmission + LOOP_L_N(t, 8) { + // IIC_SDA = (txd & 0x80) >> 7; + if (txd & 0x80) IIC_SDA_1(); else IIC_SDA_0(); + txd <<= 1; + delay_us(2); // All three delays are necessary for TEA5767 + IIC_SCL_1(); + delay_us(2); + IIC_SCL_0(); + delay_us(2); + } +} + +// Read 1 byte, when ack=1, send ACK, ack=0, send nACK +uint8_t IIC::read_byte(unsigned char ack_chr) { + unsigned char receive = 0; + SDA_IN(); // SDA is set as input + LOOP_L_N(i, 8) { + IIC_SCL_0(); + delay_us(2); + IIC_SCL_1(); + receive <<= 1; + if (READ_SDA()) receive++; + delay_us(1); + } + ack_chr ? ack() : nAck(); // Send ACK / send nACK + return receive; +} + +/******************** EEPROM ********************/ + +// Initialize the IIC interface +void BL24CXX::init() { IIC::init(); } + +// Read a byte at the specified address +// ReadAddr: the address to start reading +// Return: the byte read +uint8_t BL24CXX::readOneByte(uint16_t ReadAddr) { + uint8_t temp = 0; + IIC::start(); + if (EE_TYPE > BL24C16) { + IIC::send_byte(EEPROM_DEVICE_ADDRESS); // Send write command + IIC::wait_ack(); + IIC::send_byte(ReadAddr >> 8); // Send high address + IIC::wait_ack(); + } + else + IIC::send_byte(EEPROM_DEVICE_ADDRESS + ((ReadAddr >> 8) << 1)); // Send device address 0xA0, write data + + IIC::wait_ack(); + IIC::send_byte(ReadAddr & 0xFF); // Send low address + IIC::wait_ack(); + IIC::start(); + IIC::send_byte(EEPROM_DEVICE_ADDRESS | 0x01); // Send byte + IIC::wait_ack(); + temp = IIC::read_byte(0); + IIC::stop(); // Generate a stop condition + return temp; +} + +// Write a data at the address specified by BL24CXX +// WriteAddr: The destination address for writing data +// DataToWrite: the data to be written +void BL24CXX::writeOneByte(uint16_t WriteAddr, uint8_t DataToWrite) { + IIC::start(); + if (EE_TYPE > BL24C16) { + IIC::send_byte(EEPROM_DEVICE_ADDRESS); // Send write command + IIC::wait_ack(); + IIC::send_byte(WriteAddr >> 8); // Send high address + } + else + IIC::send_byte(EEPROM_DEVICE_ADDRESS + ((WriteAddr >> 8) << 1)); // Send device address 0xA0, write data + + IIC::wait_ack(); + IIC::send_byte(WriteAddr & 0xFF); // Send low address + IIC::wait_ack(); + IIC::send_byte(DataToWrite); // Receiving mode + IIC::wait_ack(); + IIC::stop(); // Generate a stop condition + delay(10); +} + +// Start writing data of length Len at the specified address in BL24CXX +// This function is used to write 16bit or 32bit data. +// WriteAddr: the address to start writing +// DataToWrite: the first address of the data array +// Len: The length of the data to be written 2, 4 +void BL24CXX::writeLenByte(uint16_t WriteAddr, uint32_t DataToWrite, uint8_t Len) { + LOOP_L_N(t, Len) + writeOneByte(WriteAddr + t, (DataToWrite >> (8 * t)) & 0xFF); +} + +// Start reading data of length Len from the specified address in BL24CXX +// This function is used to read 16bit or 32bit data. +// ReadAddr: the address to start reading +// Return value: data +// Len: The length of the data to be read 2,4 +uint32_t BL24CXX::readLenByte(uint16_t ReadAddr, uint8_t Len) { + uint32_t temp = 0; + LOOP_L_N(t, Len) { + temp <<= 8; + temp += readOneByte(ReadAddr + Len - t - 1); + } + return temp; +} + +// Check if BL24CXX is normal +// Return 1: Detection failed +// return 0: detection is successful +#define BL24CXX_TEST_ADDRESS 0x00 +#define BL24CXX_TEST_VALUE 0x55 + +bool BL24CXX::_check() { + return (readOneByte(BL24CXX_TEST_ADDRESS) != BL24CXX_TEST_VALUE); // false = success! +} + +bool BL24CXX::check() { + if (_check()) { // Value was written? Good EEPROM! + writeOneByte(BL24CXX_TEST_ADDRESS, BL24CXX_TEST_VALUE); // Write now and check. + return _check(); + } + return false; // success! +} + +// Start reading the specified number of data at the specified address in BL24CXX +// ReadAddr: The address to start reading is 0~255 for 24c02 +// pBuffer: the first address of the data array +// NumToRead: the number of data to be read +void BL24CXX::read(uint16_t ReadAddr, uint8_t *pBuffer, uint16_t NumToRead) { + for (; NumToRead; NumToRead--) + *pBuffer++ = readOneByte(ReadAddr++); +} + +// Start writing the specified number of data at the specified address in BL24CXX +// WriteAddr: the address to start writing, 0~255 for 24c02 +// pBuffer: the first address of the data array +// NumToWrite: the number of data to be written +void BL24CXX::write(uint16_t WriteAddr, uint8_t *pBuffer, uint16_t NumToWrite) { + for (; NumToWrite; NumToWrite--, WriteAddr++) + writeOneByte(WriteAddr, *pBuffer++); +} + +#endif // IIC_BL24CXX_EEPROM |