diff --git a/tag_fw/Newton_M3_Universal-full-flash.bin b/tag_fw/Newton_M3_Universal-full-flash.bin index f965621..258ced7 100755 Binary files a/tag_fw/Newton_M3_Universal-full-flash.bin and b/tag_fw/Newton_M3_Universal-full-flash.bin differ diff --git a/tag_fw/Newton_M3_Universal-ota.bin b/tag_fw/Newton_M3_Universal-ota.bin index 72a4bf7..e3894f0 100755 Binary files a/tag_fw/Newton_M3_Universal-ota.bin and b/tag_fw/Newton_M3_Universal-ota.bin differ diff --git a/tag_fw/hal/Newton_M3_nRF52811/HAL_Newton_M3.h b/tag_fw/hal/Newton_M3_nRF52811/HAL_Newton_M3.h index ccb9829..facf58d 100755 --- a/tag_fw/hal/Newton_M3_nRF52811/HAL_Newton_M3.h +++ b/tag_fw/hal/Newton_M3_nRF52811/HAL_Newton_M3.h @@ -126,6 +126,7 @@ struct tagSpecs { uint8_t solumType = 0; uint32_t imageSize = 0; extraButtons customSetup; + uint8_t statePinAtRest = 0; }; extern tagSpecs tag; \ No newline at end of file diff --git a/tag_fw/hal/Newton_M3_nRF52811/epd_spi.cpp b/tag_fw/hal/Newton_M3_nRF52811/epd_spi.cpp index 554c13a..de60ca9 100755 --- a/tag_fw/hal/Newton_M3_nRF52811/epd_spi.cpp +++ b/tag_fw/hal/Newton_M3_nRF52811/epd_spi.cpp @@ -24,7 +24,7 @@ bool epdReset(uint8_t type) { } else { if (attempt >= EPD_RESET_MAX) { #ifdef DEBUG_EPD - pr("EPD: Failed to reset!\n"); + printf("EPD: Failed to reset!\n"); #endif return false; } @@ -93,9 +93,14 @@ void epdConfigGPIO(bool setup) { digitalWrite(EPD_VPP, LOW); break; } - digitalWrite(EPD_RST, LOW); + if(tag.statePinAtRest == 0x01){ + digitalWrite(EPD_CS, HIGH); + digitalWrite(EPD_RST, HIGH); + }else{ + digitalWrite(EPD_CS, LOW); + digitalWrite(EPD_RST, LOW); + } digitalWrite(EPD_BS, LOW); - digitalWrite(EPD_CS, LOW); digitalWrite(EPD_DC, LOW); digitalWrite(EPD_BUSY, LOW); digitalWrite(EPD_CLK, LOW); @@ -179,6 +184,12 @@ void SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler(void) { } epdSPIXferBytes--; if (epdSPIXferBytes) { +/* +IF CS SHOULD TOGGLE CHECK FLAG HERE + epdDeselect(); + epdSelect(); +FINISH FLAG CHECKING +*/ if (epdSPIWrite != nullptr) NRF_SPI0->TXD = *(epdSPIWrite++); else diff --git a/tag_fw/hal/Newton_M3_nRF52811/tagtype_db.cpp b/tag_fw/hal/Newton_M3_nRF52811/tagtype_db.cpp index 64ece73..8349979 100755 --- a/tag_fw/hal/Newton_M3_nRF52811/tagtype_db.cpp +++ b/tag_fw/hal/Newton_M3_nRF52811/tagtype_db.cpp @@ -176,7 +176,11 @@ void identifyTagInfo() { epd = new uc8179; break; case 0x17: - epd = new epdvarbwry; + if (epdXRes == 400 && epdYRes == 168) { + epd = new epdvar2bwry; + }else{ + epd = new epdvarbwry; + } break; } @@ -347,9 +351,10 @@ void identifyTagInfo() { break; case STYPE_SIZE_30_BWRY: tag.macSuffix = 0x9490; - epd->drawDirectionRight = false; + epd->drawDirectionRight = true; tag.OEPLtype = SOLUM_M3_BWRY_30; - epd->epdMirrorV = true; + epd->epdMirrorV = false; + tag.statePinAtRest = 0x01; break; case STYPE_SIZE_013: tag.ledInverted = true; diff --git a/tag_fw/of.bin b/tag_fw/of.bin new file mode 100644 index 0000000..015473b Binary files /dev/null and b/tag_fw/of.bin differ diff --git a/tag_fw/src/epd_driver/epd_interface.h b/tag_fw/src/epd_driver/epd_interface.h index 2a37400..a02c44d 100755 --- a/tag_fw/src/epd_driver/epd_interface.h +++ b/tag_fw/src/epd_driver/epd_interface.h @@ -26,5 +26,6 @@ void selectLUT(uint8_t lut); #include "uc8159.h" #include "uc8179.h" #include "uc_variant_bwry.h" +#include "uc_variant2_bwry.h" #endif \ No newline at end of file diff --git a/tag_fw/src/epd_driver/uc_variant2_bwry.cpp b/tag_fw/src/epd_driver/uc_variant2_bwry.cpp new file mode 100644 index 0000000..3d45372 --- /dev/null +++ b/tag_fw/src/epd_driver/uc_variant2_bwry.cpp @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include +#include + +#include "hal.h" +#include "lut.h" +#include "settings.h" +#include "wdt.h" +#include "drawing.h" + +#include "epd_interface.h" +#include "uc_variant2_bwry.h" + +#define EPD_CMD_POWER_OFF 0x02 +#define EPD_CMD_POWER_ON 0x04 +#define EPD_CMD_BOOSTER_SOFT_START 0x06 +#define EPD_CMD_DEEP_SLEEP 0x07 +#define EPD_CMD_DISPLAY_START_TRANSMISSION_DTM1 0x10 +#define EPD_CMD_DISPLAY_REFRESH 0x12 +#define EPD_CMD_DISPLAY_START_TRANSMISSION_DTM2 0x13 +#define EPD_CMD_VCOM_INTERVAL 0x50 +#define EPD_CMD_RESOLUTION_SETTING 0x61 +#define EPD_CMD_UNKNOWN 0xF8 + +void epdvar2bwry::epdEnterSleep() { + epd_cmd(EPD_CMD_POWER_OFF); + epd_data(0x00); + delay(100); + + epd_cmd(EPD_CMD_DEEP_SLEEP); + epd_data(0xA5); + delay(100); +} + +void epdvar2bwry::epdSetup() { + pinMode(EPD_BS, OUTPUT); + digitalWrite(EPD_BS, 1); + epdReset(EPD_BUSY_UC); + + epdWrite(0x66, 6, 0x49, 0x55, 0x13, 0x5D, 0x05, 0x10); + + epdWrite(0xB0, 1, 0x00); + + epdWrite(0x00, 2, 0x57, 0x69); + epdWrite(0x03, 1, 0x00); + + epdWrite(EPD_CMD_BOOSTER_SOFT_START, 3, 0xD7, 0xDE, 0x12); + + epdWrite(0x41, 1, 0x00); // ok + + + epdWrite(EPD_CMD_VCOM_INTERVAL, 1, 0x17); + + epdWrite(0x60, 2, 0x0C, 0x05); + epdWrite(EPD_CMD_RESOLUTION_SETTING, 4, 0x00, 0xA8, 0x01, 0x90); + + epdWrite(0x84, 1, 0x00); + + epdWrite(0xE3, 1, 0xFF); + + epdWrite(0xE3, 1, 0xFF); + + epdWrite(EPD_CMD_POWER_ON, 0); + delay(1000); + printf("EPD INIT COMPLETE\n"); + // epdBusyWaitRising(5000); +} + +void epdvar2bwry::epdWriteDisplayData() +{ + uint8_t *drawline_b = nullptr; + uint8_t *drawline_r = nullptr; + uint8_t *drawline_y = nullptr; + + drawline_b = (uint8_t *)calloc(this->effectiveXRes / 8, 1); + drawline_r = (uint8_t *)calloc(this->effectiveXRes / 8, 1); + drawline_y = (uint8_t *)calloc(this->effectiveXRes / 8, 1); + + epd_cmd(EPD_CMD_DISPLAY_START_TRANSMISSION_DTM1); + //markData(); + //epdSelect(); + + uint8_t *buf = (uint8_t *)calloc(this->effectiveXRes / 2, 1); + uint32_t drawStart = millis(); + printf("Rendering draw... X: %u Y: %u\n", this->effectiveXRes, this->effectiveYRes); + for (uint16_t curY = 0; curY < this->effectiveYRes; curY += 1) + { + wdt60s(); + + memset(drawline_b, 0, this->effectiveXRes / 8); + memset(drawline_r, 0, this->effectiveXRes / 8); + memset(drawline_y, 0, this->effectiveXRes / 8); + + if (this->epdMirrorV) + { + drawItem::renderDrawLine(drawline_b, this->effectiveYRes - curY - 1, 0); + drawItem::renderDrawLine(drawline_r, this->effectiveYRes - curY - 1, 1); + drawItem::renderDrawLine(drawline_y, this->effectiveYRes - curY - 1, 2); + } + else + { + drawItem::renderDrawLine(drawline_b, curY, 0); + drawItem::renderDrawLine(drawline_r, curY, 1); + drawItem::renderDrawLine(drawline_y, curY, 2); + } + + for (uint16_t x = 0; x < this->effectiveXRes;) + { + // merge color buffers into one + uint8_t *temp = &(buf[x / 2]); + for (uint8_t shift = 0; shift < 2; shift++) + { + *temp <<= 4; + uint8_t curByte = x / 8; + uint8_t curMask = (1 << (7 - (x % 8))); + if ((drawline_r[curByte] & curMask)) + { + *temp |= 0x03; + } + else if (drawline_y[curByte] & curMask) + { + *temp |= 0x02; + } + else if (drawline_b[curByte] & curMask) + { + } + else + { + *temp |= 0x01; + } + x++; + } + } + // start transfer of the 'odd' data line + for (uint16_t curYyy = 0; curYyy < (this->effectiveXRes / 2); curYyy += 1) + { + epd_data(buf[curYyy]); + } + //epdSPIAsyncWrite(buf, (this->effectiveXRes / 2)); + //epdSPIWait(); + } + printf("\nRendering complete in %lu ms\n", millis() - drawStart); + + // flush the draw list, make sure items don't appear on subsequent screens + drawItem::flushDrawItems(); + + // wait until the last line of display has finished writing and clean our stuff up + //epdSPIWait(); + //epdDeselect(); + if (buf) + free(buf); + if (drawline_b) + free(drawline_b); + if (drawline_r) + free(drawline_r); + if (drawline_y) + free(drawline_y); +} + +void epdvar2bwry::selectLUT(uint8_t lut) { + // implement alternative LUTs here. Currently just reset the watchdog to two minutes, + // to ensure it doesn't reset during the much longer bootup procedure + lut += 1; // make the compiler a happy camper + wdt120s(); + return; +} + +void epdvar2bwry::draw() { + this->drawNoWait(); + this->epdWaitRdy(); + // epdBusyWaitRising(50000); + // delay(100); +} +void epdvar2bwry::drawNoWait() { + this->epdWriteDisplayData(); + printf("Starting draw\n"); + //epdWrite(0x68, 1, 0x00); + // epdBusyWaitRising(200); + // epd_cmd(EPD_CMD_DISPLAY_REFRESH); + //epdWrite(0x12, 1, 0x01); + + epdWrite(0x12, 1, 0x01); + //epd_cmd(EPD_CMD_DISPLAY_REFRESH); + printf("draw complete\n"); +} + +void epdvar2bwry::epdWaitRdy() { + epdBusyWaitRising(50000); + printf("done waiting too\n"); + delay(100); +} \ No newline at end of file diff --git a/tag_fw/src/epd_driver/uc_variant2_bwry.h b/tag_fw/src/epd_driver/uc_variant2_bwry.h new file mode 100644 index 0000000..bf939ee --- /dev/null +++ b/tag_fw/src/epd_driver/uc_variant2_bwry.h @@ -0,0 +1,17 @@ +#ifndef _EPD_BWRY_VAR2_H_ +#define _EPD_BWRY_VAR2_H_ + +class epdvar2bwry : public epdInterface { + public: + void epdSetup() ; + void epdEnterSleep() ; + void draw(); + void drawNoWait(); + void epdWaitRdy(); + void epdWriteDisplayData(); + void selectLUT(uint8_t lut); + protected: + void calculatePixels(uint8_t* dst, uint8_t* src, uint8_t color); +}; + +#endif \ No newline at end of file diff --git a/tag_fw/src/userinterface.cpp b/tag_fw/src/userinterface.cpp index a0049db..08d2f5b 100755 --- a/tag_fw/src/userinterface.cpp +++ b/tag_fw/src/userinterface.cpp @@ -236,6 +236,18 @@ void showSplashScreen() { // addFlashImage(10, 10, COLOR_BLACK, rotation::ROTATE_0, newton); addQR(100, 120, 3, 2, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]); break; + case STYPE_SIZE_30_BWRY: + fr.setFont(&FreeSansBold18pt7b); + fr.epdPrintf(2, 2, COLOR_BLACK, rotation::ROTATE_0, "OpenEPaperLink"); + fr.setFont(&FreeSans9pt7b); + fr.epdPrintf(10, 38, COLOR_BLACK, rotation::ROTATE_0, "Newton M3 3.0\" BW"); + fr.epdPrintf(171, 38, COLOR_RED, rotation::ROTATE_0, "R"); + fr.epdPrintf(184, 38, COLOR_YELLOW, rotation::ROTATE_0, "Y"); + // fr.setFont(&FreeSans9pt7b); + fr.epdPrintf(epd->Xres - 17, 0, COLOR_BLACK, rotation::ROTATE_270, "FW: %04X-%s", fwVersion, fwVersionSuffix); + fr.epdPrintf(5, epd->Yres - 20, COLOR_BLACK, rotation::ROTATE_0, "MAC: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X", mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]); + addQR(epd->Xres - 120, 42, 3, 3, "https://openepaperlink.eu/tag/0/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]); + break; } #ifdef DEBUG_BUILD drawMask(15, epd->Yres - 53, 129, 33, COLOR_BLACK); @@ -326,6 +338,7 @@ void showAPFound() { addQR(epd->Xres - 66, 47, 3, 2, "https://openepaperlink.eu/tag/1/%02X/%02X%02X%02X%02X%02X%02X%02X%02X/", tag.OEPLtype, mSelfMac[7], mSelfMac[6], mSelfMac[5], mSelfMac[4], mSelfMac[3], mSelfMac[2], mSelfMac[1], mSelfMac[0]); break; case STYPE_SIZE_029: + case STYPE_SIZE_30_BWRY: fr.setFont(&FreeSansBold18pt7b); fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "AP Found"); fr.setFont(&FreeSans9pt7b); @@ -493,6 +506,7 @@ void showNoAP() { fr.epdPrintf(10, 129, COLOR_BLACK, rotation::ROTATE_0, "the NFC-wake area with your phone"); break; case STYPE_SIZE_029: + case STYPE_SIZE_30_BWRY: fr.setFont(&FreeSansBold18pt7b); fr.epdPrintf(7, 7, COLOR_BLACK, rotation::ROTATE_0, "No AP Found"); fr.setFont(&FreeSans9pt7b); @@ -599,6 +613,7 @@ void showNoAP() { fr.epdPrintf(10, 109, COLOR_BLACK, rotation::ROTATE_0, "can force a retry now by scanning"); fr.epdPrintf(10, 129, COLOR_BLACK, rotation::ROTATE_0, "the NFC-wake area with your phone"); break; + } addOverlay(); draw(); diff --git a/uircm330.bin b/uircm330.bin new file mode 100644 index 0000000..ff00810 Binary files /dev/null and b/uircm330.bin differ