Skip to content
Open
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
72 changes: 72 additions & 0 deletions boards/muzi_base_duo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"build": {
"arduino": {
"ldscript": "nrf52840_s140_v6.ld"
},
"core": "nRF5",
"cpu": "cortex-m4",
"extra_flags": "-DARDUINO_NRF52840_MUZI_BASE_DUO -DNRF52840_XXAA",
"f_cpu": "64000000L",
"hwids": [
[
"0x239A",
"0x4405"
],
[
"0x239A",
"0x0029"
],
[
"0x239A",
"0x002A"
]
],
"usb_product": "muzi_base_duo",
"mcu": "nrf52840",
"variant": "MUZI_BASE_DUO",
"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": "nrf52.cfg"
},
"frameworks": [
"arduino"
],
"name": "Muzi Base Duo",
"upload": {
"maximum_ram_size": 248832,
"maximum_size": 815104,
"speed": 115200,
"use_1200bps_touch": true,
"require_upload_port": true,
"wait_for_upload_port": true,
"protocol": "nrfutil",
"protocols": [
"jlink",
"nrfjprog",
"nrfutil",
"stlink"
]
},
"url": "https://github.com/muzi-works",
"vendor": "MuziWorks"
}
39 changes: 39 additions & 0 deletions src/helpers/radiolib/CustomLR1121.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#pragma once

#include <RadioLib.h>
#include "MeshCore.h"

class CustomLR1121 : public LR1121 {
bool _rx_boosted = false;

public:
CustomLR1121(Module *mod) : LR1121(mod) { }

size_t getPacketLength(bool update) override {
size_t len = LR1121::getPacketLength(update);
if (len == 0 && getIrqStatus() & RADIOLIB_LR11X0_IRQ_HEADER_ERR) {
// we've just received a corrupted packet
// this may have triggered a bug causing subsequent packets to be shifted
// call standby() to return radio to known-good state
// recvRaw will call startReceive() to restart rx
MESH_DEBUG_PRINTLN("LR1121: got header err, calling standby()");
standby();
}
return len;
}

float getFreqMHz() const { return freqMHz; }

int16_t setRxBoostedGainMode(bool en) {
_rx_boosted = en;
return LR1121::setRxBoostedGainMode(en);
}

bool getRxBoostedGainMode() const { return _rx_boosted; }

bool isReceiving() {
uint16_t irq = getIrqStatus();
bool detected = ((irq & RADIOLIB_LR11X0_IRQ_SYNC_WORD_HEADER_VALID) || (irq & RADIOLIB_LR11X0_IRQ_PREAMBLE_DETECTED));
return detected;
}
};
34 changes: 34 additions & 0 deletions src/helpers/radiolib/CustomLR1121Wrapper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include "CustomLR1121.h"
#include "RadioLibWrappers.h"
#include "LR11x0Reset.h"

class CustomLR1121Wrapper : public RadioLibWrapper {
public:
CustomLR1121Wrapper(CustomLR1121& radio, mesh::MainBoard& board) : RadioLibWrapper(radio, board) { }
void doResetAGC() override { lr11x0ResetAGC((LR11x0 *)_radio, ((CustomLR1121 *)_radio)->getFreqMHz()); }
bool isReceivingPacket() override {
return ((CustomLR1121 *)_radio)->isReceiving();
}
float getCurrentRSSI() override {
float rssi = -110;
((CustomLR1121 *)_radio)->getRssiInst(&rssi);
return rssi;
}

void onSendFinished() override {
RadioLibWrapper::onSendFinished();
_radio->setPreambleLength(16); // overcomes weird issues with small and big pkts
}

float getLastRSSI() const override { return ((CustomLR1121 *)_radio)->getRSSI(); }
float getLastSNR() const override { return ((CustomLR1121 *)_radio)->getSNR(); }

void setRxBoostedGainMode(bool en) override {
((CustomLR1121 *)_radio)->setRxBoostedGainMode(en);
}
bool getRxBoostedGainMode() const override {
return ((CustomLR1121 *)_radio)->getRxBoostedGainMode();
}
};
103 changes: 103 additions & 0 deletions src/helpers/ui/SH1107Display.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#include "SH1107Display.h"
#include <Adafruit_GrayOLED.h>
#include "Adafruit_SH110X.h"

#ifndef DISPLAY_ROTATION
#define DISPLAY_ROTATION 0
#endif

bool SH1107Display::i2c_probe(TwoWire &wire, uint8_t addr)
{
wire.beginTransmission(addr);
uint8_t error = wire.endTransmission();
return (error == 0);
}

bool SH1107Display::begin()
{
bool result = display.begin(DISPLAY_ADDRESS, true) && i2c_probe(Wire, DISPLAY_ADDRESS);
if (result) {
display.setRotation(DISPLAY_ROTATION);
}
return result;
}

void SH1107Display::turnOn()
{
display.oled_command(SH110X_DISPLAYON);
uint8_t cmd[] = {0xD5, 0xF0};
display.oled_commandList(cmd, 2);
_isOn = true;
}

void SH1107Display::turnOff()
{
display.oled_command(SH110X_DISPLAYOFF);
_isOn = false;
}

void SH1107Display::clear()
{
display.clearDisplay();
display.display();
}

void SH1107Display::startFrame(Color bkg)
{
display.clearDisplay(); // TODO: apply 'bkg'
display.setContrast(120); // 0-127. default setting was causing some flickering.
// display.SH110X_SETPRECHARGE(255);
_color = SH110X_WHITE;
display.setTextColor(_color);
display.setTextSize(1);
display.cp437(true); // Use full 256 char 'Code Page 437' font
}

void SH1107Display::setTextSize(int sz)
{
display.setTextSize(sz);
}

void SH1107Display::setColor(Color c)
{
_color = (c != 0) ? SH110X_WHITE : SH110X_BLACK;
display.setTextColor(_color);
}

void SH1107Display::setCursor(int x, int y)
{
display.setCursor(x, y);
}

void SH1107Display::print(const char *str)
{
display.print(str);
}

void SH1107Display::fillRect(int x, int y, int w, int h)
{
display.fillRect(x, y, w, h, _color);
}

void SH1107Display::drawRect(int x, int y, int w, int h)
{
display.drawRect(x, y, w, h, _color);
}

void SH1107Display::drawXbm(int x, int y, const uint8_t *bits, int w, int h)
{
display.drawBitmap(x, y, bits, w, h, SH110X_WHITE);
}

uint16_t SH1107Display::getTextWidth(const char *str)
{
int16_t x1, y1;
uint16_t w, h;
display.getTextBounds(str, 0, 0, &x1, &y1, &w, &h);
return w;
}

void SH1107Display::endFrame()
{
display.display();
}
46 changes: 46 additions & 0 deletions src/helpers/ui/SH1107Display.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#pragma once

#include "DisplayDriver.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#define SH110X_NO_SPLASH
#include <Adafruit_SH110X.h>

#ifndef PIN_OLED_RESET
#define PIN_OLED_RESET -1
#ifndef PIN_OLED_12V_EN
#define PIN_OLED_12V_EN -1
#endif
#endif

#ifndef DISPLAY_ADDRESS
#define DISPLAY_ADDRESS 0x3c
#endif

class SH1107Display : public DisplayDriver
{
Adafruit_SH1107 display;
bool _isOn;
uint8_t _color;

bool i2c_probe(TwoWire &wire, uint8_t addr);

public:
SH1107Display() : DisplayDriver(128, 128), display(128, 128, &Wire, PIN_OLED_RESET, PIN_OLED_12V_EN) { _isOn = false; }
bool begin();

bool isOn() override { return _isOn; }
void turnOn() override;
void turnOff() override;
void clear() override;
void startFrame(Color bkg = DARK) override;
void setTextSize(int sz) override;
void setColor(Color c) override;
void setCursor(int x, int y) override;
void print(const char *str) override;
void fillRect(int x, int y, int w, int h) override;
void drawRect(int x, int y, int w, int h) override;
void drawXbm(int x, int y, const uint8_t *bits, int w, int h) override;
uint16_t getTextWidth(const char *str) override;
void endFrame() override;
};
50 changes: 50 additions & 0 deletions variants/muzi_base_duo/muzi_base_duoBoard.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#include <Arduino.h>
#include <Wire.h>

#include "muzi_base_duoBoard.h"

#ifdef NRF52_POWER_MANAGEMENT
const PowerMgtConfig power_config = {
.lpcomp_ain_channel = PWRMGT_LPCOMP_AIN,
.lpcomp_refsel = PWRMGT_LPCOMP_REFSEL,
.voltage_bootlock = PWRMGT_VOLTAGE_BOOTLOCK
};

void muzi_base_duoBoard::initiateShutdown(uint8_t reason) {
// Disable LoRa module power before shutdown
if (reason == SHUTDOWN_REASON_LOW_VOLTAGE ||
reason == SHUTDOWN_REASON_BOOT_PROTECT) {
configureVoltageWake(power_config.lpcomp_ain_channel, power_config.lpcomp_refsel);
}

enterSystemOff(reason);
}
#endif // NRF52_POWER_MANAGEMENT

void muzi_base_duoBoard::begin() {
NRF52BoardDCDC::begin();
pinMode(PIN_VBAT_READ, INPUT);
pinMode(SCREEN_12V_ENABLE, OUTPUT);
digitalWrite(SCREEN_12V_ENABLE, HIGH); // Enable 12V power for SH1107 display
delay(250);
Wire.begin();
// delay(1000); // wait for display to initialize. otherwise it doesn't come up on boot.

#ifdef PIN_USER_BTN
pinMode(PIN_USER_BTN, INPUT_PULLUP);
#endif
pinMode(PIN_BUTTON1, INPUT_PULLUP);
pinMode(PIN_BUTTON2, INPUT_PULLUP);
pinMode(PIN_BUTTON3, INPUT_PULLUP);
pinMode(PIN_BUTTON4, INPUT_PULLUP);
pinMode(PIN_BUTTON5, INPUT_PULLUP);
pinMode(PIN_BUTTON6, INPUT_PULLUP);

// #if defined(PIN_BOARD_SDA) && defined(PIN_BOARD_SCL)
// Wire.setPins(PIN_BOARD_SDA, PIN_BOARD_SCL);
// #endif
#ifdef NRF52_POWER_MANAGEMENT
checkBootVoltage(&power_config);
#endif
// delay(10); // give LR1121 some time to power up
}
37 changes: 37 additions & 0 deletions variants/muzi_base_duo/muzi_base_duoBoard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#pragma once

#include <MeshCore.h>
#include <Arduino.h>
#include <helpers/NRF52Board.h>

class muzi_base_duoBoard : public NRF52BoardDCDC {
protected:
#ifdef NRF52_POWER_MANAGEMENT
void initiateShutdown(uint8_t reason) override;
#endif

public:
muzi_base_duoBoard() : NRF52Board("MUZI_BASE_DUO_OTA") {}
void begin();

#define BATTERY_SAMPLES 8

uint16_t getBattMilliVolts() override {
analogReadResolution(12);
analogReference(AR_INTERNAL_3_0);
delay(1);

uint32_t raw = 0;
for (int i = 0; i < BATTERY_SAMPLES; i++) {
raw += analogRead(PIN_VBAT_READ);
}
raw = raw / BATTERY_SAMPLES;

// ADC_MULTIPLIER is the voltage divider ratio
return (raw * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096;
}

const char* getManufacturerName() const override {
return "Muzi Base Duo";
}
};
Loading