Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions boards/heltec_mesh_pocket.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
["0x239A", "0x4405"],
["0x239A", "0x0029"],
["0x239A", "0x002A"]
],
"usb_product": "HT-n5262",
"mcu": "nrf52840",
"variant": "heltec_mesh_pocket",
"variants_dir": "variants",
"bsp": {
"name": "adafruit"
},
"softdevice": {
"sd_flags": "-DS140",
"sd_name": "s140",
"sd_version": "6.1.1",
"sd_fwid": "0x00B6"
},
"bootloader": {
"settings_addr": "0xFF000"
}
},
"connectivity": ["bluetooth"],
"debug": {
"jlink_device": "nRF52840_xxAA",
"onboard_tools": ["jlink"],
"svd_path": "nrf52840.svd",
"openocd_target": "nrf52840-mdk-rs"
},
"frameworks": ["arduino"],
"name": "Heltec nrf (Adafruit BSP)",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"protocol": "nrfutil",
"protocols": ["jlink", "nrfjprog", "nrfutil", "stlink"],
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true
},
"url": "https://heltec.org/project/meshpocket/",
"vendor": "Heltec"
}
1 change: 1 addition & 0 deletions examples/simple_repeater/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -818,6 +818,7 @@ void setup() {
#ifdef DISPLAY_CLASS
if (display.begin()) {
display.startFrame();
display.setCursor(0, 0);
display.print("Please wait...");
display.endFrame();
}
Expand Down
1 change: 1 addition & 0 deletions examples/simple_room_server/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,7 @@ void setup() {
#ifdef DISPLAY_CLASS
if (display.begin()) {
display.startFrame();
display.setCursor(0, 0);
display.print("Please wait...");
display.endFrame();
}
Expand Down
23 changes: 10 additions & 13 deletions src/helpers/ui/GxEPDDisplay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,6 @@
#define DISPLAY_ROTATION 3
#endif

#define SCALE_X 1.5625f // 200 / 128
#define SCALE_Y 1.5625f // 200 / 128

bool GxEPDDisplay::begin() {
display.epd2.selectSPI(SPI1, SPISettings(4000000, MSBFIRST, SPI_MODE0));
SPI1.begin();
Expand Down Expand Up @@ -84,7 +81,7 @@ void GxEPDDisplay::setColor(Color c) {
void GxEPDDisplay::setCursor(int x, int y) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display.setCursor(x*SCALE_X, (y+10)*SCALE_Y);
display.setCursor((x+offset_x)*scale_x, (y+offset_y)*scale_y);
}

void GxEPDDisplay::print(const char* str) {
Expand All @@ -97,15 +94,15 @@ void GxEPDDisplay::fillRect(int x, int y, int w, int h) {
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display.fillRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color);
display.fillRect(x*scale_x, y*scale_y, w*scale_x, h*scale_y, _curr_color);
}

void GxEPDDisplay::drawRect(int x, int y, int w, int h) {
display_crc.update<int>(x);
display_crc.update<int>(y);
display_crc.update<int>(w);
display_crc.update<int>(h);
display.drawRect(x*SCALE_X, y*SCALE_Y, w*SCALE_X, h*SCALE_Y, _curr_color);
display.drawRect(x*scale_x, y*scale_y, w*scale_x, h*scale_y, _curr_color);
}

void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
Expand All @@ -115,24 +112,24 @@ void GxEPDDisplay::drawXbm(int x, int y, const uint8_t* bits, int w, int h) {
display_crc.update<int>(h);
display_crc.update<uint8_t>(bits, w * h / 8);
// Calculate the base position in display coordinates
uint16_t startX = x * SCALE_X;
uint16_t startY = y * SCALE_Y;
uint16_t startX = x * scale_x;
uint16_t startY = y * scale_y;

// Width in bytes for bitmap processing
uint16_t widthInBytes = (w + 7) / 8;

// Process the bitmap row by row
for (uint16_t by = 0; by < h; by++) {
// Calculate the target y-coordinates for this logical row
int y1 = startY + (int)(by * SCALE_Y);
int y2 = startY + (int)((by + 1) * SCALE_Y);
int y1 = startY + (int)(by * scale_y);
int y2 = startY + (int)((by + 1) * scale_y);
int block_h = y2 - y1;

// Scan across the row bit by bit
for (uint16_t bx = 0; bx < w; bx++) {
// Calculate the target x-coordinates for this logical column
int x1 = startX + (int)(bx * SCALE_X);
int x2 = startX + (int)((bx + 1) * SCALE_X);
int x1 = startX + (int)(bx * scale_x);
int x2 = startX + (int)((bx + 1) * scale_x);
int block_w = x2 - x1;

// Get the current bit
Expand All @@ -153,7 +150,7 @@ uint16_t GxEPDDisplay::getTextWidth(const char* str) {
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
return ceil((w + 1) / SCALE_X);
return ceil((w + 1) / scale_x);
}

void GxEPDDisplay::endFrame() {
Expand Down
23 changes: 18 additions & 5 deletions src/helpers/ui/GxEPDDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
#include <Fonts/FreeSansBold12pt7b.h>
#include <Fonts/FreeSans18pt7b.h>

#define GxEPD2_DISPLAY_CLASS GxEPD2_BW
#define GxEPD2_DRIVER_CLASS GxEPD2_150_BN // DEPG0150BN 200x200, SSD1681, (FPC8101), TTGO T5 V2.4.1

#include <epd/GxEPD2_150_BN.h> // 1.54" b/w
#include <epd/GxEPD2_213_B74.h> // 2.13" b/w
#include <CRC32.h>

#include "DisplayDriver.h"
Expand All @@ -26,7 +24,19 @@

class GxEPDDisplay : public DisplayDriver {

#if defined(HELTEC_MESH_POCKET)
GxEPD2_BW<EINK_DISPLAY_MODEL, EINK_DISPLAY_MODEL::HEIGHT> display;
const float scale_x = EINK_SCALE_X;
const float scale_y = EINK_SCALE_Y;
const float offset_x = EINK_X_OFFSET;
const float offset_y = EINK_Y_OFFSET;
#else
GxEPD2_BW<GxEPD2_150_BN, 200> display;
const float scale_x = 1.5625f;
const float scale_y = 1.5625f;
const float offset_x = 0;
const float offset_y = 10;
#endif
bool _init = false;
bool _isOn = false;
uint16_t _curr_color;
Expand All @@ -35,8 +45,11 @@ class GxEPDDisplay : public DisplayDriver {

public:
// there is a margin in y...
GxEPDDisplay() : DisplayDriver(128, 128), display(GxEPD2_150_BN(DISP_CS, DISP_DC, DISP_RST, DISP_BUSY)) {
}
#if defined(HELTEC_MESH_POCKET)
GxEPDDisplay() : DisplayDriver(128, 128), display(EINK_DISPLAY_MODEL(PIN_DISPLAY_CS, PIN_DISPLAY_DC, PIN_DISPLAY_RST, PIN_DISPLAY_BUSY)) {}
#else
GxEPDDisplay() : DisplayDriver(128, 128), display(GxEPD2_150_BN(DISP_CS, DISP_DC, DISP_RST, DISP_BUSY)) {}
#endif

bool begin();

Expand Down
72 changes: 72 additions & 0 deletions variants/mesh_pocket/MeshPocket.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include <Arduino.h>
#include "MeshPocket.h"
#include <bluefruit.h>
#include <Wire.h>

static BLEDfu bledfu;

static void connect_callback(uint16_t conn_handle)
{
(void)conn_handle;
MESH_DEBUG_PRINTLN("BLE client connected");
}

static void disconnect_callback(uint16_t conn_handle, uint8_t reason)
{
(void)conn_handle;
(void)reason;

MESH_DEBUG_PRINTLN("BLE client disconnected");
}

void HeltecMeshPocket::begin() {
// for future use, sub-classes SHOULD call this from their begin()
startup_reason = BD_STARTUP_NORMAL;
Serial.begin(115200);
pinMode(PIN_VBAT_READ, INPUT);

pinMode(PIN_USER_BTN, INPUT);
}

bool HeltecMeshPocket::startOTAUpdate(const char* id, char reply[]) {
// Config the peripheral connection with maximum bandwidth
// more SRAM required by SoftDevice
// Note: All config***() function must be called before begin()
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16);

Bluefruit.begin(1, 0);
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
Bluefruit.setTxPower(4);
// Set the BLE device name
Bluefruit.setName("MESH_POCKET_OTA");

Bluefruit.Periph.setConnectCallback(connect_callback);
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);

// To be consistent OTA DFU should be added first if it exists
bledfu.begin();

// Set up and start advertising
// Advertising packet
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
Bluefruit.Advertising.addTxPower();
Bluefruit.Advertising.addName();

/* Start Advertising
- Enable auto advertising if disconnected
- Interval: fast mode = 20 ms, slow mode = 152.5 ms
- Timeout for fast mode is 30 seconds
- Start(timeout) with timeout = 0 will advertise forever (until connected)

For recommended advertising interval
https://developer.apple.com/library/content/qa/qa1931/_index.html
*/
Bluefruit.Advertising.restartOnDisconnect(true);
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds

strcpy(reply, "OK - started");
return true;
}
45 changes: 45 additions & 0 deletions variants/mesh_pocket/MeshPocket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include <Arduino.h>
#include <MeshCore.h>

// built-ins
#define PIN_VBAT_READ 29
#define PIN_BAT_CTL 34
#define MV_LSB (3000.0F / 4096.0F) // 12-bit ADC with 3.0V input range

class HeltecMeshPocket : public mesh::MainBoard {
protected:
uint8_t startup_reason;

public:
void begin();
uint8_t getStartupReason() const override { return startup_reason; }



uint16_t getBattMilliVolts() override {
int adcvalue = 0;
analogReadResolution(12);
analogReference(AR_INTERNAL_3_0);
pinMode(PIN_BAT_CTL, OUTPUT); // battery adc can be read only ctrl pin set to high
pinMode(PIN_VBAT_READ, INPUT);
digitalWrite(PIN_BAT_CTL, HIGH);

delay(10);
adcvalue = analogRead(PIN_VBAT_READ);
digitalWrite(PIN_BAT_CTL, LOW);

return (uint16_t)((float)adcvalue * MV_LSB * 4.9);
}

const char* getManufacturerName() const override {
return "Heltec MeshPocket";
}

void reboot() override {
NVIC_SystemReset();
}

bool startOTAUpdate(const char* id, char reply[]) override;
};
Loading