diff --git a/ext/e-ink/Waveshare.h b/ext/e-ink/Waveshare.h new file mode 100644 index 0000000..8bdcb53 --- /dev/null +++ b/ext/e-ink/Waveshare.h @@ -0,0 +1,102 @@ +#ifndef E_INK_WAVESHARE +#define E_INK_WAVESHARE + +#include +#include "../../Debug.h" + + + + +/** + * base-class for Waveshare SPI E-Ink displays + * subclasses for every display type implement the actual methods + */ +template class Waveshare { + + static constexpr const char* NAME = "E-Ink"; + + SPI& spi; + +public: + + Waveshare(SPI& spi) : spi(spi) { + debugMod4(NAME, "ctor() CS:%d BUSY:%d RST:%d DC:%d", PIN_CS, PIN_BUSY, PIN_RST, PIN_DC); + MyGPIO::setInput(PIN_BUSY); + MyGPIO::setOutput(PIN_RST); + MyGPIO::setOutput(PIN_DC); + MyGPIO::setOutput(PIN_CS); + } + +protected: + + void reset() { + debugMod(NAME, "reset()"); + MyGPIO::clear(PIN_RST); + usleep(200*1000); + MyGPIO::set(PIN_RST); + usleep(200*1000); + } + + void sendCommand(uint8_t command) { + MyGPIO::clear(PIN_DC); + transfer(command); + } + + void sendData(uint8_t data) { + MyGPIO::set(PIN_DC); + transfer(data); + } + + void transfer(uint8_t data) { + MyGPIO::clear(PIN_CS); // select + spi.writeByte(data); + MyGPIO::clear(PIN_CS); // unselect + } + + void waitUntilIdle() { + debugMod(NAME, "waitUntilIdle()"); + while(MyGPIO::get(PIN_BUSY) == 0) {usleep(200*1000);} + debugMod(NAME, "OK"); + } + + void lut(uint8_t c, uint8_t l, const uint8_t* p) { + sendCommand(c); + for (int i = 0; i < l; i++, p++) { + sendData(*p); + } + } + + void send1(uint8_t cmd, uint8_t v1) { + sendCommand(cmd); + sendData(v1); + } + void send2(uint8_t cmd, uint8_t v1, uint8_t v2) { + sendCommand(cmd); + sendData(v1); + sendData(v2); + } + void send3(uint8_t cmd, uint8_t v1, uint8_t v2, uint8_t v3) { + sendCommand(cmd); + sendData(v1); + sendData(v2); + sendData(v3); + } + void send4(uint8_t cmd, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4) { + sendCommand(cmd); + sendData(v1); + sendData(v2); + sendData(v3); + sendData(v4); + } + void send5(uint8_t cmd, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5) { + sendCommand(cmd); + sendData(v1); + sendData(v2); + sendData(v3); + sendData(v4); + sendData(v5); + } + +}; + +#endif // E_INK_WAVESHARE diff --git a/ext/e-ink/Waveshare_4_2.h b/ext/e-ink/Waveshare_4_2.h new file mode 100644 index 0000000..d6c874e --- /dev/null +++ b/ext/e-ink/Waveshare_4_2.h @@ -0,0 +1,255 @@ + +#include "Waveshare.h" + +template class Waveshare_4_2 : public Waveshare { + + static constexpr const char* NAME = "E-Ink 4.2\""; + +public: + + enum class Mode { + BLACK_WHITE, + BLACK_WHITE_RED, + }; + +public: + + Waveshare_4_2(SPI& spi) : Waveshare(spi) { + + } + +public: + + struct Window { + uint16_t x1; // must be multiple of 8 + uint16_t y1; + uint16_t w; // must be multiple of 8 + uint16_t h; + Window(uint16_t x1, uint16_t y1, uint16_t w, uint16_t h) : x1(x1), y1(y1), w(w), h(h) {} + }; + + void setWindow(Window& win) { + this->sendCommand(0x90); + this->sendData((win.x1) >> 8); + this->sendData((win.x1) >> 0); + this->sendData((win.x1+win.w-1) >> 8); + this->sendData((win.x1+win.w-1) >> 0); + this->sendData(win.y1 >> 8); + this->sendData(win.y1 >> 0); + this->sendData((win.y1+win.h-1) >> 8); + this->sendData((win.y1+win.h-1) >> 0); + this->sendData(0x0); // 0 = refresh only the window, 1 = refresh everything?? + } + + void enableWindow() { + this->sendCommand(0x91); + } + + void disableWindow() { + this->sendCommand(0x92); + } + + void init(Mode mode) { + + debugMod(NAME, "init()"); + + this->reset(); + + this->send3(0x06, 0x17, 0x17, 0x17); // BOOSTER_SOFT_START + this->sendCommand(0x04); // POWER_ON + this->waitUntilIdle(); + + uint8_t cfg = 0x0F; + if (mode == Mode::BLACK_WHITE) {cfg |= (1<<4);} + this->send1(0x00, cfg); // PANEL_SETTING + this->send1(0x50, 0xF7); // VCOM_AND_DATA_INTERVAL_SETTING + + //this->sendCommand(0x10);//DATA_START_TRANSMISSION_1 + //usleep(10*1000); + + debugMod(NAME, "init() complete"); + + } + + void loadBlack(const uint8_t* black) { + this->sendCommand(0x10); + if (black) { + for (int i = 0; i < 400*300/8; ++i) {this->sendData(~reverse(black[i]));} + } else { + for (int i = 0; i < 400*300/8; ++i) {this->sendData(~0x00);} + } + this->sendCommand(0x11); + } + + void loadRed(const uint8_t* red) { + this->sendCommand(0x13); + if (red) { + for (int i = 0; i < 400*300/8; ++i) {this->sendData(~reverse(red[i]));} + } else { + for (int i = 0; i < 400*300/8; ++i) {this->sendData(~0x00);} + } + this->sendCommand(0x11); + } + + static uint8_t reverse(uint8_t a) { + return + ((a & 0x1) << 7) | ((a & 0x2) << 5) | + ((a & 0x4) << 3) | ((a & 0x8) << 1) | + ((a & 0x10) >> 1) | ((a & 0x20) >> 3) | + ((a & 0x40) >> 5) | ((a & 0x80) >> 7); + } + + void show() { + + debugMod(NAME, "refresh"); + this->sendCommand(0x12);//DISPLAY_REFRESH + usleep(100*1000); + this->waitUntilIdle(); + debugMod(NAME, "refresh done"); + + debugMod(NAME, "sleep"); + this->send1(0x50, 0x17);//VCOM_AND_DATA_INTERVAL_SETTING + this->send1(0x82, 0x00);//VCM_DC_SETTING_REGISTER, to solve Vcom drop + this->send4(0x01, 0x02, 0x00, 0x00, 0x00);//POWER_SETTING + this->waitUntilIdle(); + this->sendCommand(0x02);//POWER_OFF + debugMod(NAME, "sleep done"); + + } + + +private: + + unsigned char lut_dc_4in2[44] = { + 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, + 0x02, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + //R21H + unsigned char lut_ww_4in2[42] = { + 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + //R22H r + unsigned char lut_bw_4in2[42] = { + 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + //R24H b + unsigned char lut_bb_4in2[42] = { + 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + + //R23H w + unsigned char lut_wb_4in2[42] = { + 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + }; + +}; + + + +/* + +int EPD_Init_4in2() +{ + EPD_Reset(); + + EPD_SendCommand(0x01);//POWER_SETTING + EPD_SendData(0x03); // VDS_EN, VDG_EN + EPD_SendData(0x00); // VCOM_HV, VGHL_LV[1], VGHL_LV[0] + EPD_SendData(0x2F); // VDH + EPD_SendData(0x2F); // VDL + EPD_SendData(0xFF); // VDHR + + EPD_Send_3(0x06, 0x17, 0x17, 0x17);//BOOSTER_SOFT_START + EPD_SendCommand(0x04);//POWER_ON + EPD_WaitUntilIdle(); + + EPD_Send_2(0x00, 0xBF, 0x0B);//PANEL_SETTING: // KW-BF KWR-AF BWROTP 0f + EPD_Send_1(0x30, 0x3C);//PLL_CONTROL: 3A 100HZ, 29 150Hz, 39 200HZ, 31 171HZ + + EPD_Send_4(0x61, 1, 144, 1, 44);// RESOLUTION_SETTING: HI(W), LO(W), HI(H), LO(H) + EPD_Send_1(0x82, 0x12);// VCM_DC_SETTING + EPD_Send_1(0x50, 0x97);// VCOM_AND_DATA_INTERVAL_SETTING: VBDF 17|D7 VBDW 97 VBDB 57 VBDF F7 VBDW 77 VBDB 37 VBDR B7 + + EPD_lut(0x20,44,&lut_dc_4in2[0]);// LUT_FOR_VCOM + EPD_lut(0x21,42,&lut_ww_4in2[0]);// LUT_WHITE_TO_WHITE + EPD_lut(0x22,42,&lut_bw_4in2[0]);// LUT_BLACK_TO_WHITE + EPD_lut(0x23,42,&lut_wb_4in2[0]);// LUT_WHITE_TO_BLACK + EPD_lut(0x24,42,&lut_bb_4in2[0]);// LUT_BLACK_TO_BLACK + + EPD_SendCommand(0x10);//DATA_START_TRANSMISSION_1 + delay(2); + for(int i = 0; i < 400*300; i++)EPD_SendData(0xFF);//Red channel + + EPD_SendCommand(0x13);//DATA_START_TRANSMISSION_2 + delay(2); + return 0; + +} + +unsigned char lut_dc_4in2b[] = +{ + 0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00, 0x17, 0x17, 0x00, 0x00, + 0x02, 0x00, 0x0A, 0x01, 0x00, 0x00, 0x01, 0x00, 0x0E, 0x0E, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +//R21H +unsigned char lut_ww_4in2b[] = +{ + 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +//R22H r +unsigned char lut_bw_4in2b[] = +{ + 0x40, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x40, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0xA0, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +//R24H b +unsigned char lut_bb_4in2b[] = +{ + 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +//R23H w +unsigned char lut_wb_4in2b[] = +{ + 0x80, 0x17, 0x00, 0x00, 0x00, 0x02, 0x90, 0x17, 0x17, 0x00, 0x00, 0x02, 0x80, 0x0A, + 0x01, 0x00, 0x00, 0x01, 0x50, 0x0E, 0x0E, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +int EPD_Init_4in2b() +{ + EPD_Reset(); + EPD_Send_3(0x06,0x17,0x17,0x17);//BOOSTER_SOFT_START + EPD_SendCommand(0x04);//POWER_ON + EPD_WaitUntilIdle(); + EPD_Send_1(0x00, 0x0F);//PANEL_SETTING + EPD_Send_1(0x50,0xF7);// VCOM_AND_DATA_INTERVAL_SETTING + + EPD_SendCommand(0x10);//DATA_START_TRANSMISSION_1 + delay(2); + return 0; +} +*/ diff --git a/ext/rf/SX1276.h b/ext/rf/SX1276.h index 0a2520b..b289db2 100644 --- a/ext/rf/SX1276.h +++ b/ext/rf/SX1276.h @@ -169,6 +169,9 @@ public: // set output power to 17 dBm setTxPower(17); + // we use explicit header mode for RX/TX + explicitHeaderMode(); + // put in standby mode idle(); @@ -351,9 +354,9 @@ public: if (isTransmitting()) {return 0;} // put in standby mode - idle(); + //idle(); - explicitHeaderMode(); + //explicitHeaderMode(); // reset FIFO address and payload length writeRegister(REG_FIFO_ADDR_PTR, 0); @@ -412,7 +415,7 @@ public: uint8_t irqFlags = readRegister(REG_IRQ_FLAGS); - explicitHeaderMode(); + //explicitHeaderMode(); // clear all current IRQ flags writeRegister(REG_IRQ_FLAGS, irqFlags); diff --git a/ext/sens/BME280.h b/ext/sens/BME280.h index 843b998..ea970f4 100644 --- a/ext/sens/BME280.h +++ b/ext/sens/BME280.h @@ -73,7 +73,7 @@ private: // read all 24 calibration bytes for temperature and pressure uint8_t b1[24]; - readRegister(REG_DIG_T1, b1, 24); + i2c.readReg(ADDR7, REG_DIG_T1, 24, b1); cal.dig_T1 = (b1[1] << 8) | b1[0]; cal.dig_T2 = (b1[3] << 8) | b1[2]; @@ -90,8 +90,8 @@ private: cal.dig_P9 = (b1[23] << 8) | b1[22]; // humidity - readRegister(0xA1, &cal.dig_H1, 1); - readRegister(0xE1, b1, 7); + i2c.readReg(ADDR7, 0xA1, 1, &cal.dig_H1); + i2c.readReg(ADDR7, 0xE1, 7, b1); cal.dig_H2 = (b1[1] << 8) | b1[0]; cal.dig_H3 = b1[3]; cal.dig_H4 = (b1[3] << 4) | (b1[4] & 0b000001111); @@ -101,9 +101,9 @@ private: //os_printf("calib temp: %d %d %d\n", cal.dig_T1, cal.dig_T2, cal.dig_T3); //os_printf("calib pres: %d %d %d %d %d %d %d %d %d\n", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9); //os_printf("calib humi: %d %d %d %d %d %d\n", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6); - debugMod3(NAME, "calTemp: %d %d %d", cal.dig_T1, cal.dig_T2, cal.dig_T3); - debugMod9(NAME, "calPres: %d %d %d %d %d %d %d %d %d", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9); - debugMod6(NAME, "calHumi: %d %d %d %d %d %d", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6); + //debugMod3(NAME, "calTemp: %d %d %d", cal.dig_T1, cal.dig_T2, cal.dig_T3); + //debugMod9(NAME, "calPres: %d %d %d %d %d %d %d %d %d", cal.dig_P1, cal.dig_P2, cal.dig_P3, cal.dig_P4, cal.dig_P5, cal.dig_P6, cal.dig_P7, cal.dig_P8, cal.dig_P9); + //debugMod6(NAME, "calHumi: %d %d %d %d %d %d", cal.dig_H1, cal.dig_H2, cal.dig_H3, cal.dig_H4, cal.dig_H5, cal.dig_H6); } @@ -115,8 +115,8 @@ private: const uint8_t cfgMode = 0b11; const uint8_t cfg1 = (cfgHumi << 1); const uint8_t cfg2 = (cfgTemp << 5) | (cfgPres << 2) | (cfgMode << 0); - writeRegister(REG_CTRL1, &cfg1, 1); - writeRegister(REG_CTRL2, &cfg2, 1); + i2c.writeReg(ADDR7, REG_CTRL1, 1, &cfg1); + i2c.writeReg(ADDR7, REG_CTRL2, 1, &cfg2); } @@ -133,7 +133,7 @@ public: uint8_t getStatus() { uint8_t res[1]; - readRegister(REG_STATUS, res, 1); + i2c.readReg(ADDR7, REG_STATUS, 1, res); //os_printf("Status: %d \n", res[0]); return 0; } @@ -141,58 +141,59 @@ public: /** get current pressure in hPa */ float getPressure() { uint8_t res[3]; - readRegister(REG_PRESSURE, res, 3); + i2c.readReg(ADDR7, REG_PRESSURE, 3, res); //os_printf("res: %d - %d - %d \n", res[0], res[1], res[2]); const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4; const uint32_t pres = BME280_compensate_P_int64(tmp); const float presF = pres / 256.0f / 100.0f; // convert from Q24.8 to float and from Pa to hPa - const uint32_t p0 = pres / 256; - const uint32_t p1 = (uint32_t) presF; - const uint32_t p2 = (presF - p1) * 100000; - debugMod4(NAME, "[pres] ADC: %d -> %d Pa | %d.%d hPa", tmp, p0, p1,p2); + //const uint32_t p0 = pres / 256; + //const uint32_t p1 = (uint32_t) presF; + //const uint32_t p2 = (presF - p1) * 100000; + //debugMod4(NAME, "[pres] ADC: %d -> %d Pa | %d.%d hPa", tmp, p0, p1,p2); return presF; } float getTemperature() { uint8_t res[3]; - readRegister(REG_TEMPERATURE, res, 3); + i2c.readReg(ADDR7, REG_TEMPERATURE, 3, res); //os_printf("res: %d - %d - %d \n", res[0], res[1], res[2]); const uint32_t tmp = ((res[0] << 16) | (res[1] << 8) | (res[2] << 0)) >> 4; const int32_t temp = BME280_compensate_T_int32(tmp); const float tempF = temp / 100.0f; - debugMod2(NAME, "[temp] ADC: %d -> %d", tmp, temp); + //debugMod2(NAME, "[temp] ADC: %d -> %d", tmp, temp); return tempF; } float getHumidity() { uint8_t res[2]; - readRegister(REG_HUMIDITY, res, 2); + i2c.readReg(ADDR7, REG_HUMIDITY, 2, res); //os_printf("res: %d - %d \n", res[0], res[1]); const uint32_t tmp = (res[0] << 8) | (res[1] << 0); const int32_t humi = bme280_compensate_H_int32(tmp); const float humiF = humi / 1024.0f; - const uint16_t h0 = humi / 1024; - const uint16_t h1 = (uint16_t) humiF; - const uint16_t h2 = (humiF - humi) * 10000; - debugMod4(NAME, "[humi] ADC: %d -> %d -> %d.%d %%", tmp, h0, h1,h2); + //const uint16_t h0 = humi / 1024; + //const uint16_t h1 = (uint16_t) humiF; + //const uint16_t h2 = (humiF - humi) * 10000; + //debugMod4(NAME, "[humi] ADC: %d -> %d -> %d.%d %%", tmp, h0, h1,h2); return humiF; } + /* bool readRegister(const uint8_t addr, uint8_t* dst, const uint8_t len) { bool ok; // address the slave in write mode and select the first register to read ok = i2c.startWrite(ADDR7); - if (!ok) {os_printf("failed start write\n"); return false;} + if (!ok) {printf("failed start write\n"); return false;} ok = i2c.writeByteAndCheck(addr); - if (!ok) {os_printf("failed to select register %d\n", addr); return false;} + if (!ok) {printf("failed to select register %d\n", addr); return false;} //i2c::stop(); // address the slave in read mode and read [len] registers ok = i2c.startRead(ADDR7); - if (!ok) {os_printf("failed start read\n"); return 0;} + if (!ok) {printf("failed start read\n"); return 0;} i2c.readBytes(dst, len); // done @@ -207,11 +208,11 @@ public: // address the slave in write mode and select the first register to read ok = i2c.startWrite(ADDR7); - if (!ok) {os_printf("failed start write\n"); return false;} + if (!ok) {printf("failed start write\n"); return false;} ok = i2c.writeByteAndCheck(addr); - if (!ok) {os_printf("failed to select register %d\n", addr); return false;} + if (!ok) {printf("failed to select register %d\n", addr); return false;} ok = i2c.writeBytesAndCheck(src, len); - if (!ok) {os_printf("failed to write register contents \n"); return false;} + if (!ok) {printf("failed to write register contents \n"); return false;} // done i2c.stop(); @@ -219,7 +220,7 @@ public: } - + */ private: diff --git a/ext/time/DS3231.h b/ext/time/DS3231.h index 8f96f35..fd5e368 100644 --- a/ext/time/DS3231.h +++ b/ext/time/DS3231.h @@ -3,7 +3,7 @@ #include "../../io/SoftI2C.h" -class DS3231 { +template class DS3231 { static constexpr uint8_t ADDR7 = 0x68; @@ -11,11 +11,17 @@ class DS3231 { static constexpr uint8_t REG_MINUTES = 0x01; static constexpr uint8_t REG_HOURS = 0x02; + I2C& i2c; public: + DS3231(I2C& i2c) : i2c(i2c) { + ; + } + bool isPresent() { - return i2c::query(ADDR7); + //return i2c::query(ADDR7); + return i2c.query(ADDR7); } struct Time { @@ -37,7 +43,7 @@ public: Res get() { uint8_t buf[8]; - readRegister(0x00, buf, 8); + i2c.readReg(ADDR7, 0x00, 8, buf); Res res; @@ -49,8 +55,8 @@ public: res.date.m = (((buf[5] & 0b00010000)>>4)*10) + (buf[5] & 0b1111); res.date.y = (((buf[6] & 0b11110000)>>4)*10) + (buf[6] & 0b1111); - os_printf("%d %d %d \n", res.time.h, res.time.m, res.time.s); - os_printf("%d %d %d \n", res.date.d, res.date.m, res.date.y); + printf("%d %d %d \n", res.time.h, res.time.m, res.time.s); + printf("%d %d %d \n", res.date.d, res.date.m, res.date.y); return res; @@ -62,7 +68,7 @@ public: buf[0] = ((s/10)<<4) + (s % 10); buf[1] = ((m/10)<<4) + (m % 10); buf[2] = ((h/10)<<4) + (h % 10); - writeRegister(0x00, buf, 3); + i2c.writeReg(ADDR7, 0x00, 3, buf); } @@ -72,12 +78,13 @@ public: buf[0] = ((d/10)<<4) + (d % 10); buf[1] = ((m/10)<<4) + (m % 10); buf[2] = ((y/10)<<4) + (y % 10); - writeRegister(0x04, buf, 3); + i2c.writeReg(ADDR7, 0x04, 3, buf); } private: + /* bool readRegister(const uint8_t addr, uint8_t* dst, const uint8_t len) { bool ok; @@ -118,6 +125,7 @@ private: return true; } + */ }; diff --git a/io/SoftI2C.h b/io/SoftI2C.h index b706c62..d6333c8 100644 --- a/io/SoftI2C.h +++ b/io/SoftI2C.h @@ -15,6 +15,7 @@ template class SoftI2C { inline void sdaDirIn() {MyGPIO::setInput(PIN_SDA);} inline void sclDirOut() {MyGPIO::setOutput(PIN_SCL);} + inline void sclDirIn() {MyGPIO::setInput(PIN_SCL);} inline void sdaHi() {MyGPIO::set(PIN_SDA);} inline void sdaLo() {MyGPIO::clear(PIN_SDA);} @@ -29,7 +30,7 @@ template class SoftI2C { __asm__ __volatile__("nop"); } } else { - for (uint16_t i = 0; i < 1024; ++i) { + for (uint16_t i = 0; i < 2048; ++i) { __asm__ __volatile__("nop"); } } @@ -92,7 +93,8 @@ public: waitLong(); sdaHi(); - sdaDirIn(); // free the bus + sdaDirIn(); // free the bus + sclDirIn(); // TESTING. free the bus waitLong(); @@ -147,6 +149,17 @@ public: stop(); return ok; } + + inline void queryAll() { + debugMod(NAME, "queryAll()") + for (uint8_t i = 0; i < 128; ++i) { + if (query(i)) { + debugMod1(NAME, "found %d", i) + } + waitLong(); + if (i%16 == 0) {vTaskDelay(100 / portTICK_PERIOD_MS);} + } + } @@ -166,14 +179,14 @@ public: // select register(s) to read ok = startWrite(addr); - if (!ok) {debugMod(NAME, "failed start write(1)"); return false;} + if (!ok) {debugMod(NAME, "failed start read(1)"); return false;} ok = writeByteAndCheck(reg); if (!ok) {debugMod(NAME, "failed select register"); return false;} stop(); // read register(s) ok = startRead(addr); - if (!ok) {debugMod(NAME, "failed start write(2)"); return false;} + if (!ok) {debugMod(NAME, "failed start read(2)"); return false;} readBytes(dst, len); stop(); @@ -215,6 +228,7 @@ private: inline void _writeBit(const bool out) { //sdaDirOut(); // switch to output mode if(out) {sdaHi();} else {sdaLo();} // apply data + waitShort(); // wait for data to settle. IMPORTANT! sclHi(); // clock pulse waitShort(); sclLo(); @@ -254,6 +268,7 @@ private: inline bool _readAck() { sdaDirIn(); // switch to input mode const uint8_t res = _readBit(); + //printf("%d\n", res); return res == 0; // ACK when input pulled low } diff --git a/io/SoftSPI.h b/io/SoftSPI.h index 6b18d72..a79bbaa 100644 --- a/io/SoftSPI.h +++ b/io/SoftSPI.h @@ -5,8 +5,6 @@ #include "../Platforms.h" #include "../Debug.h" - - #pragma GCC push_options #pragma GCC optimize ("O2")