aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/libs/BL24CXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Marlin/src/libs/BL24CXX.cpp')
-rw-r--r--Marlin/src/libs/BL24CXX.cpp272
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