Skip to content

Commit

Permalink
feat: support platform SAMG21G18A
Browse files Browse the repository at this point in the history
  • Loading branch information
todd-herbert committed Sep 15, 2023
1 parent cb7781f commit 0c14166
Show file tree
Hide file tree
Showing 23 changed files with 371 additions and 31 deletions.
26 changes: 20 additions & 6 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,21 @@ Run-time drawing, using Adafruit-GFX.
- [Page Size](#page-size)
- [Power Switching](#power-switching)
- [Fast mode (Partial Refresh)](#fast-mode-partial-refresh)
- [Troubleshooting](#troubleshooting)
- [Installation](#installation)
- [Acknowledgements](#acknowledgements)



## Supported Platforms

* ATmega328P  ( Arduino UNO R3,  Arduino Nano,  etc. )
* ATmega2560   ( Arduino Mega 2560 )
* ESP32
* ESP8266


Platform | Tested
------------|-------------------------------
ATmega328P | Arduino Uno R3, Arduino Nano
ATmega2560 | Arduino Mega 2560
ESP32 | Devkit V1
ESP8266 | NodeMcu v3
SAMD21G18A | Protoneer Nano ARM

## Supported Displays

Expand Down Expand Up @@ -166,6 +168,7 @@ See your boards's wiring page for specific information:
* [**Wiring:** Arduino Mega 2560](/docs/Wiring/wiring_m2560.md)
* [**Wiring:** ESP32](/docs/Wiring/wiring_esp32.md)
* [**Wiring:** ESP8266](/docs/Wiring/wiring_esp8266.md)
* [**Wiring:** SAMD21G18A](/docs/Wiring/wiring_samd21g18a.md)

## To *page*, or not to *page*

Expand Down Expand Up @@ -303,6 +306,17 @@ The trade-off is that images drawn in fast mode are of a lower quality. The proc
Call [`setFastmodeOn()`](/docs/API.md#fastmodeon) to enable.<br />
Call [`setFastmodeOff()`](/docs/API.md#fastmodeoff) to return to normal.
## Troubleshooting
* **Double-check your wiring**<br />
On breadboard, or header pins, it is easy to be one row out.<br />
Make sure to use a level-shifter, if needed.
* **Disconnect and Reconnect**<br />
If the display has been used incorrectly, it can get "stuck".<br />
Remove all power from the display for 5 seconds.
## Installation
**Arduino:** Library can be installed to Arduino IDE with *Sketch* -> *Include Library* -> *Add .Zip Library..*, or through the built-in Library Manager.
Expand Down
Binary file added docs/Wiring/nano33iot_spi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions docs/Wiring/wiring_samd21g18a.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# Heltec E-ink Modules
## Wiring:SAMD21G18A

**✅ SAMD21G18A uses 3.3V logic. It can connect directly to display.**

Display | SAMD21G18A
--------|--------
VCC | 3.3V
GND | GND
D/C | D2
SDI | MOSI (COPI)
CS | D4
CLK | SCK
BUSY | D5


### Where are *MOSI* and *SCK*?
*Good question.* The location depends on your board.

These suggested locations are untested: I do not own either board. Please let me know if they do not work.

Arduino Zero | Arduino Nano 33 IoT
-------------|--------------------
![Diagram: suspected zero pin locations](zero_spi.png) | ![Diagram: suspected nano 33 IoT pin locations](nano33iot_spi.png)

### (Optional) Changing MOSI and SCK pins

All pin assignments can be changed, using an extended constructor:
```cpp
DISPLAY_CLASS(DC_PIN, CS_PIN, BUSY_PIN, SDI_PIN, CLK_PIN);
```
Due to hardware limitations, only certain wiring pairs are valid for SDI and CLK:
SDI pin | SCK pin
--------|--------
D2 | D5
D4 | D3
D4 | D5
D5 | D3
D10 | D12
D11 | D12
D11 | D13
D12 | D13
A1 | A2
If your selection is invalid, your board's `LED_BUILTIN` will blink out an "SOS".
### (Optional) Suggested additional wiring, for power saving
```cpp
void setup() {
// GPIO 7, PNP transistor
display.usePowerSwitching(7, PNP);
//Later, when required:
display.externalPowerOff();
display.externalPowerOn();
}
```

![schematic of display connected to Arduino Zero, using PNP transistor as a switch](zero_power_switching.png)
Binary file added docs/Wiring/zero_power_switching.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/Wiring/zero_spi.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name=heltec-eink-modules
version=3.0.0
version=3.1.0
author=Todd Herbert
maintainer=Todd Herbert
sentence=Third party graphics library for Heltec E-Ink modules.
paragraph=AdafruitGFX and Arduino Uno R3 support.
category=Display
url=https://github.com/todd-herbert/heltec-eink-modules
architectures=avr, esp32, esp8266
architectures=avr, esp32, esp8266, samd
8 changes: 4 additions & 4 deletions src/Displays/BaseDisplay/Bounds/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ uint16_t WindowBounds::left() {
uint16_t WindowBounds::getWindowBounds(WindowBounds::side request) {

// Boolean LUT (x:side, y:rotation): after considering rotation, does requested edge need to measure from opposite edge.
static const uint8_t rotswap_lut[4] = { B0000,
B0101,
B1111,
B1010 };
static const uint8_t rotswap_lut[4] = { 0b0000,
0b0101,
0b1111,
0b1010 };

// Handle setFlip() - first part
// If flipping, we need to find the opposite edge, and right at the end, measure from the opposite side
Expand Down
2 changes: 2 additions & 0 deletions src/Displays/BaseDisplay/base.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ class BaseDisplay: public GFX {

protected:
void init();
void lateInit(); // Platform which refuse to use SPI in constructor. Called before methods
void grabPageMemory(); // Allocate dynamic memory to the pagefile(s) (image buffer)
void freePageMemory(); // Release pagefile memory
void sendCommand(uint8_t command); // Send SPI Command to display (see datasheets)
Expand Down Expand Up @@ -138,6 +139,7 @@ class BaseDisplay: public GFX {

// SPI
const SPISettings spi_settings = SPISettings(200000, MSBFIRST, SPI_MODE0);
bool init_done = false; // If using lateInit(), has it run once?

// External power switch
uint8_t pin_power = -1; // Pin connected to switch / transistor gate
Expand Down
11 changes: 11 additions & 0 deletions src/Displays/BaseDisplay/hardware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ void BaseDisplay::wait() {

/// Write one page to the panel memory
void BaseDisplay::writePage() {
// SAMD21: Setup SPI
#if LATE_INIT
lateInit();
#endif

// Calculate rotated x start and stop values (y is already done via paging)
int16_t sx, sy, ex, ey;
specifyMemoryArea(sx, sy, ex, ey); // Virtual, derived class
Expand Down Expand Up @@ -149,6 +154,12 @@ void BaseDisplay::externalPowerOn() {

// SPI resumes
SPI_BEGIN();

// SAMD21: Move the SPI pins back to custom location
#ifdef __SAMD21G18A__
if (pin_sdi != DEFAULT_SDI && pin_clk != DEFAULT_CLK)
PinMux().setSPIPins(pin_sdi, pin_clk);
#endif

// Re-load settings for full-refresh
fastmodeOff();
Expand Down
18 changes: 18 additions & 0 deletions src/Displays/BaseDisplay/mode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@

// Slow, detailed updates
void BaseDisplay::fastmodeOff() {

// SAMD21: Setup SPI
#if LATE_INIT
lateInit();
#endif

fastmode_state = Fastmode::OFF;
reset();
configFull();
Expand All @@ -17,6 +23,12 @@ void BaseDisplay::fastmodeOff() {
// Fast, low quality updates.
// Use sparingly.
void BaseDisplay::fastmodeOn() {

// SAMD21: Setup SPI
#if LATE_INIT
lateInit();
#endif

if(fastmode_state == NOT_SET)
clear(false); // Initialize display memory, if needed

Expand All @@ -35,6 +47,12 @@ void BaseDisplay::fastmodeOn() {
// Fastest, low quality updates. Unstable.
// Use with caution.
void BaseDisplay::fastmodeTurbo() {

// SAMD21: Setup SPI
#if LATE_INIT
lateInit();
#endif

if(fastmode_state == NOT_SET)
clear(false); // Initialize dispaly memory, if needed

Expand Down
30 changes: 29 additions & 1 deletion src/Displays/BaseDisplay/setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ void BaseDisplay::init() {

// Prepare SPI
digitalWrite(pin_cs, HIGH);
SPI_BEGIN();
#if !LATE_INIT
SPI_BEGIN();
#endif

// Calculate pagefile size
pagefile_height = constrain(pagefile_height, 1, MAX_PAGE_HEIGHT);
Expand All @@ -63,13 +65,39 @@ void BaseDisplay::init() {
#if PRESERVE_IMAGE
grabPageMemory();
fullscreen(); // Window change, clears page

// SAMD21 can't call SPI.begin from a constructor. See BaseDisplay::lateInit()
#if LATE_INIT
return;
#endif

writePage(); // Make sure display memory is also blanked
init_done = true;
#else
// Otherwise, just set the region
fullscreen();
#endif
}

// Same platforms won't run SPI commands from constructor. This method is called later to finish the job.
void BaseDisplay::lateInit() {

// Start SPI and clear display mem
if (!init_done) {
SPI.begin();
init_done = true;

// SAMD21: change SPI pins if requested
#ifdef __SAMD21G18A__
if (pin_sdi != DEFAULT_SDI && pin_clk != DEFAULT_CLK)
PinMux().setSPIPins(pin_sdi, pin_clk);
#endif

// After all that, clear the display memory
writePage();
}
}

// Set configuration of custom power-swiching circuit, then power up
void BaseDisplay::usePowerSwitching(uint8_t pin, SwitchType type) {
this->pin_power = pin;
Expand Down
5 changes: 3 additions & 2 deletions src/Platforms/ESP32.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

// Name
#define PLATFORM_NAME ESP32
// Don't use fallback settigs
#define PLATFORM_SUPPORTED true

// SPI
#define SPI_BEGIN() ( SPI.begin(pin_clk, -1, pin_sdi, -1) )
#define CAN_SPECIFY_SPI_PINS true
#define DEFAULT_SDI MOSI
#define DEFAULT_CLK SCK
#define LATE_INIT false

// Paging
#define DEFAULT_PAGE_HEIGHT panel_height // Indicate that we want the full display
Expand Down
5 changes: 3 additions & 2 deletions src/Platforms/ESP8266.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,15 @@
#define abs(x) ((x)>0?(x):-(x))
#define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt)))

// Name
#define PLATFORM_NAME ESP8266
// Don't use fallback settigs
#define PLATFORM_SUPPORTED true

// SPI
#define SPI_BEGIN() ( SPI.begin() )
#define CAN_SPECIFY_SPI_PINS false
#define DEFAULT_SDI -1
#define DEFAULT_CLK -1
#define LATE_INIT false

// Paging
#define DEFAULT_PAGE_HEIGHT panel_height // Indicate that we want the full display
Expand Down
7 changes: 3 additions & 4 deletions src/Platforms/M1280.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@
// If building for ATmega1280
#ifdef __AVR_ATmega1280__

#warning - ATmega1280 support is untested.

// Short Name
#define PLATFORM_NAME ATMEGA1280
// Don't use fallback settigs
#define PLATFORM_SUPPORTED true

// SPI
#define SPI_BEGIN() ( SPI.begin() )
#define CAN_SPECIFY_SPI_PINS false
#define DEFAULT_SDI MOSI
#define DEFAULT_CLK SCK
#define LATE_INIT false

// Paging
#define DEFAULT_PAGE_HEIGHT panel_height
Expand Down
5 changes: 3 additions & 2 deletions src/Platforms/M2560.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
// If building for ATmega2560
#ifdef __AVR_ATmega2560__

// Short Name
#define PLATFORM_NAME ATMEGA2560
// Don't use fallback settigs
#define PLATFORM_SUPPORTED true

// SPI
#define SPI_BEGIN() ( SPI.begin() )
#define CAN_SPECIFY_SPI_PINS false
#define DEFAULT_SDI MOSI
#define DEFAULT_CLK SCK
#define LATE_INIT false

// Paging
#define DEFAULT_PAGE_HEIGHT panel_height
Expand Down
5 changes: 3 additions & 2 deletions src/Platforms/M328P.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@
// If building for ATmega328P (UNO, or compatible)
#ifdef __AVR_ATmega328P__

// Short Name
#define PLATFORM_NAME ATMEGA328P
// Don't use fallback settigs
#define PLATFORM_SUPPORTED true

// SPI
#define SPI_BEGIN() ( SPI.begin() )
#define CAN_SPECIFY_SPI_PINS false
#define DEFAULT_SDI 11
#define DEFAULT_CLK 13
#define LATE_INIT false

// Paging
#define DEFAULT_PAGE_HEIGHT 20
Expand Down
30 changes: 30 additions & 0 deletions src/Platforms/SAMD21G18A/SAMD21G18A.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Specific options for SAMD21G18A

#ifndef __PLATFORM_FALLBACK_H__
#define __PLATFORM_FALLBACK_H__
// Check if not otherwise handled
#ifdef __SAMD21G18A__

#include "pin_mux.h"

// Don't use fallback settigs
// Don't use fallback settigs
#define PLATFORM_SUPPORTED true

// SPI

#define SPI_BEGIN() ( SPI.begin() )
#define CAN_SPECIFY_SPI_PINS true
#define DEFAULT_SDI MOSI
#define DEFAULT_CLK SCK
#define LATE_INIT true

// Paging
#define DEFAULT_PAGE_HEIGHT panel_height
#define MAX_PAGE_HEIGHT panel_height // Size, in bytes: MAX_PAGE_HEIGHT * (width / 8)
#define PRESERVE_IMAGE true // Allow the profile to preserve image

#endif

#endif
Loading

0 comments on commit 0c14166

Please sign in to comment.