Skip to content

Commit c69ff05

Browse files
committed
setup env for testing and setting fuses
1 parent 7d96405 commit c69ff05

25 files changed

+12385
-28
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@
66
/.vscode
77
/build*
88

9-
arduino-cli*
9+
arduino-cli*
10+
bootloader-feather_m0-*

README.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,43 @@
11
# Build Instructions
22

3-
Arduino SDK, pin layout of board is identical to a Adafruit Feather M0.
3+
Arduino SDK, pin layout of board is identical to a Adafruit Feather M0.
44

55
## Linux Arduino SDK and Dependency Setup
66
tools/linux/sdk-setup.sh
77

88
tools/linux/build.sh
99

1010
## Windows Arduino SDK and Dependency Setup
11-
win/tools/sdk-setup.ps1
11+
tools/win/sdk-setup.ps1
1212

13-
win/tools/build.ps1
13+
tools/win/build.ps1
14+
15+
## Mac Arduino SDK and Dependency Setup
16+
tools/osx/sdk-setup.ps1
17+
18+
tools/osx/build.ps1
19+
20+
# Bootloader Instructions
21+
22+
1. flash adafruit bootloader https://github.com/adafruit/uf2-samdx1
23+
2. set boot brotection fuses to 8kb (bootprot fuse value 0x2)
24+
3. (optional) flash pawos_setup.hex
25+
4. disable BOD33 fuse via pawos_setup.hex or preffered programmer device
1426

1527
# Flash Instructions
1628

17-
will be identical to arduino sdk for now
29+
1. connect device via usb
30+
2. double click reset button to enter bootloader
31+
3. flash pawos via arduino-cli (tools/<plat>/flash.sh)
32+
33+
# Update Instructions
34+
1. wake PawPet from sleep
35+
2. connect via USB
36+
3. flash pawos via arduino-cli (tools/<plat>/flash.sh)
37+
38+
TODO: update instructions that use UF2 instead, should be possible to use a script to put the device into bootloader mode, and then copy the file over via system file browser, or dynamically detect the device attach via usb id and drive name.
1839

19-
ideally use custom script for handing images to internal flash via msc and new firmware over UF2 format
40+
TODO: consider a self packaged C# exe or python script?
2041

2142
TODO: look into using openocd for flashing bootloader
2243

Untitled-2.md

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
TODO:
2+
validate clock toggle rate is 30hz and fix counters as needed
3+
need phillips screws for the back
4+
need more heat set inserts
5+
need more 470/480 ohm 805 resistors
6+
7+
8+
9+
https://forum.arduino.cc/t/samd21-power-consumption-too-high-in-active-mode/668966/2
10+
11+
12+
Generic clock generator 0 8 division factor bits - DIV[7:0]
13+
Generic clock generator 1 16 division factor bits - DIV[15:0]
14+
Generic clock generators 2 5 division factor bits - DIV[4:0]
15+
Generic clock generators 3 - 8 8 division factor bits - DIV[7:0]
16+
17+
rtc will be on anyways for time keeping
18+
19+
add BOD33 disable in bootloader flashing scripts?
20+
21+
condition where NVM RWS being 1 in bootloader will prevent startup below 2.1v
22+
which is in theory near the end of useful battery life anyways
23+
24+
add ability for poweroff requiring push button reset?
25+
from system menu and for when battery is low
26+
- how to do this? disable all clocks?
27+
28+
29+
display says it operates down 2.7v
30+
- max frame frequency of 65hz?
31+
- claims EXTCOMIN should be below framerate frequency, does not indicate why
32+
- extcom freq of 54-65hz
33+
34+
3) A still image should be displayed less than two hours, if it is necessary to display still image longer than two
35+
hour, display image data must be refreshed in order to avoid sticking image on LCD panel
36+
37+
Memory LCDs do not generate this signal internally. It must be supplied using one of two methods:
38+
software, or external clock...
39+
When the software clock is selected [EXTMODE = L], bit V of the command bit string sets the state of VCOM.
40+
See Figure 2. This bit must toggle (by writing to the panel) at least once per second.
41+
42+
Power Scenario 1
43+
1hz write 1hz refresh
44+
Here all of the pixels will be written to the panel once per second. For the 1.35-inch panel, the quiescent
45+
current for the panel is 2.1μA. Each write to the panel (assuming that the entire panel is written), takes
46+
360μA; and lasts for about 5.38ms (assuming a 2 MHz SPI clock speed).
47+
If averaged over a second, this amounts to an “average” currant draw of approximately 2μa. Therefore, the
48+
panel would have an average power draw of 20.5μW (5V operation). Note that a VCOM toggle can be done
49+
whenever the panel is written to, including a data write.
50+
51+
Power Scenario 2
52+
30 sec write, 1hz refresh
53+
Here, we write all the pixels to the panel only every 30 seconds. The current required to write to the panel
54+
“averaged” over that time is approximately 0.1μA. If VCOM is toggled once a second (using the Change
55+
VCOM command), the additional power draw for this action (assuming that it is done 29 times) is an average
56+
of 0.1μA. Therefore the average power draw over the 30-second period becomes 11.5μW. See Figure 10.
57+
Applying these conditions to the 2.7-inch panel: writing all pixels to the whole panel once a second takes an
58+
average of 485μW. Writing all pixels once every 30 seconds (with a 1-second VCOM toggle) takes 135μW.
59+
60+
61+
62+
63+
uint32_t userWord0 = *((uint32_t *)NVMCTRL_USER); // Read fuses for user word 0
64+
uint32_t userWord1 = *((uint32_t *)(NVMCTRL_USER + 4)); // Read fuses for user word 1
65+
NVMCTRL->CTRLB.bit.CACHEDIS = 1; // Disable the cache
66+
NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set the address
67+
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_EAR | // Erase the auxiliary user page row
68+
NVMCTRL_CTRLA_CMDEX_KEY;
69+
while (!NVMCTRL->INTFLAG.bit.READY) // Wait for the NVM command to complete
70+
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear the error flags
71+
NVMCTRL->ADDR.reg = NVMCTRL_AUX0_ADDRESS / 2; // Set the address
72+
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_PBC | // Clear the page buffer
73+
NVMCTRL_CTRLA_CMDEX_KEY;
74+
while (!NVMCTRL->INTFLAG.bit.READY) // Wait for the NVM command to complete
75+
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear the error flags
76+
*((uint32_t *)NVMCTRL_USER) = userWord0 & ~FUSES_BOD33_EN_Msk; // Disable the BOD33 enable fuse in user word 0
77+
*((uint32_t *)(NVMCTRL_USER + 4)) = userWord1; // Copy back user word 1 unchanged
78+
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMD_WAP | // Write to the user page
79+
NVMCTRL_CTRLA_CMDEX_KEY;
80+
while (!NVMCTRL->INTFLAG.bit.READY) // Wait for the NVM command to complete
81+
NVMCTRL->STATUS.reg |= NVMCTRL_STATUS_MASK; // Clear the error flags
82+
NVMCTRL->CTRLB.bit.CACHEDIS = 0; // Enable the cache

pawos.ino

Lines changed: 67 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
#include <Adafruit_TinyUSB.h>
33
#include <Arduino.h>
44
#include <FatLib/FatFileSystem.h>
5-
#include <RTCZero.h>
65
#include <SPI.h>
76
#include <WInterrupts.h>
87
#include <wiring_private.h>
98

109
#include "src/lib/ArduinoLowPower.h"
1110
#include "src/lib/PawPet_FlashTransport.h"
11+
#include "src/lib/RTCZero.h"
1212

1313
#include "src/common.h"
1414
#include "src/config.h"
@@ -17,6 +17,11 @@
1717
#include "src/states/gamestate.h"
1818

1919
// #define DEBUG 1
20+
#define INSTALLER 1
21+
22+
#ifdef INSTALLER
23+
#include "src/states/pawos_install.h"
24+
#endif
2025

2126
#ifdef DEBUG
2227
#include <ZeroRegs.h>
@@ -28,7 +33,6 @@
2833
static const SPIFlash_Device_t possible_devices[] = {MX25R1635F};
2934
SPIClass flashSPI(&sercom2, FLASH_MISO, FLASH_SCK, FLASH_MOSI, SPI_PAD_0_SCK_1, SERCOM_RX_PAD_2);
3035
PawPet_FlashTransport_SPI flashTransport(FLASH_CS, flashSPI);
31-
Adafruit_SPIFlash flash(&flashTransport);
3236

3337
SPIClass dispSPI(&sercom4, SHARP_MISO, SHARP_SCK, SHARP_MOSI, SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0);
3438
PetDisplay display(&dispSPI, SHARP_SS, DISP_WIDTH, DISP_HEIGHT);
@@ -57,6 +61,9 @@ uint16_t intBat = 300;
5761

5862
void setup(void)
5963
{
64+
g::g_flash = new Adafruit_SPIFlash(&flashTransport);
65+
Adafruit_SPIFlash& flash = *g::g_flash;
66+
6067
#ifdef DEBUG
6168
Serial.begin(9600);
6269

@@ -86,7 +93,37 @@ void setup(void)
8693
pinMode(PIN_BUTTON_C, INPUT_PULLUP);
8794

8895
pinMode(PIN_BUTTON_P, INPUT_PULLUP);
89-
LowPower.attachInterruptWakeup(PIN_BUTTON_P, buttonWakeupCallback, FALLING);
96+
// LowPower.attachInterruptWakeup(PIN_BUTTON_P, buttonWakeupCallback, FALLING);
97+
98+
EExt_Interrupts in = g_APinDescription[PIN_BUTTON_P].ulExtInt;
99+
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
100+
return;
101+
102+
attachInterrupt(PIN_BUTTON_P, buttonWakeupCallback, FALLING);
103+
104+
// enable EIC clock
105+
GCLK->CLKCTRL.bit.CLKEN = 0; // disable GCLK module
106+
while (GCLK->STATUS.bit.SYNCBUSY) {}
107+
108+
GCLK->CLKCTRL.reg = (uint16_t)(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK3 |
109+
GCLK_CLKCTRL_ID(GCM_EIC)); // EIC clock switched on GCLK3
110+
while (GCLK->STATUS.bit.SYNCBUSY) {}
111+
112+
// GCLK->GENCTRL.reg =
113+
// (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_RUNSTDBY); // source for
114+
// GCLK2 is OSCULP32K
115+
// while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
116+
117+
// GCLK->GENCTRL.bit.RUNSTDBY = 1; // GCLK2 run standby
118+
// while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
119+
120+
// Enable wakeup capability on pin in case being used during sleep
121+
EIC->WAKEUP.reg |= (1 << in);
122+
123+
/* Errata: Make sure that the Flash does not power all the way down
124+
* when in sleep mode. */
125+
126+
NVMCTRL->CTRLB.bit.SLEEPPRM = NVMCTRL_CTRLB_SLEEPPRM_DISABLED_Val;
90127

91128
pinMode(PIN_UP, INPUT_PULLUP);
92129
pinMode(PIN_LEFT, INPUT_PULLUP);
@@ -108,7 +145,7 @@ void setup(void)
108145
flash.begin(possible_devices);
109146

110147
// Init file system on the flash
111-
g::g_fatfs = new FatFileSystem;
148+
g::g_fatfs = new FatFileSystem();
112149
g::g_stats.filesysFound = g::g_fatfs->begin(&flash);
113150
g::g_stats.flashSize = flash.size();
114151

@@ -133,7 +170,11 @@ void setup(void)
133170

134171
buttonWakeup = false;
135172
nextSleepTime = 40000;
173+
#ifdef INSTALLER
174+
currentState = new InstallMenu();
175+
#else
136176
currentState = new MenuState();
177+
#endif
137178

138179
g::g_rtc.begin();
139180
g::g_rtc.setHours(0);
@@ -156,13 +197,15 @@ void setup(void)
156197
delay(500);
157198
USBDevice.attach();
158199
#endif
159-
160-
tone(PIN_BEEPER, NOTE_C4, 250);
200+
if (!g::g_stats.filesysFound)
201+
{
202+
tone(PIN_BEEPER, NOTE_C4, 250);
203+
}
161204
}
162205

163206
uint32_t sleepTicks = 0;
164-
uint8_t keysPressed = 0;
165-
uint8_t prevKeysPressed = 0;
207+
uint8_t keysState = 0;
208+
uint8_t prevKeysState = 0;
166209

167210
uint32_t currentTimeMs = 0;
168211
uint32_t frameTimeMs = 0;
@@ -180,11 +223,11 @@ void loop(void)
180223
Watchdog.reset();
181224

182225
//// UPDATE ////
183-
keysPressed |= readButtons();
226+
keysState |= readButtons();
184227

185228
currentTimeMs = millis();
186229

187-
if (keysPressed)
230+
if (keysState)
188231
{
189232
nextSleepTime = currentTimeMs + 60000;
190233
}
@@ -195,9 +238,11 @@ void loop(void)
195238
{
196239

197240
prevFrameMs = currentTimeMs;
198-
199-
g::g_keyPressed = keysPressed;
200-
g::g_keyReleased = ~(prevKeysPressed) & (keysPressed);
241+
// held is currenlty just previous update, a function of update loop speed
242+
// between 66 and 2000 ms
243+
g::g_keyPressed = ~(prevKeysState)&keysState;
244+
g::g_keyReleased = prevKeysState & ~(keysState);
245+
g::g_keyHeld = prevKeysState & keysState;
201246

202247
uint32_t t1 = millis();
203248
GameState *nextState = currentState->update();
@@ -235,6 +280,8 @@ void loop(void)
235280
if (currentState->redraw)
236281
{
237282
display.fillDisplayBuffer();
283+
display.setCursor(0, 8);
284+
display.setTextColor(PET_BLACK);
238285
currentState->draw(&display);
239286

240287
// TODO, draw overlay should say if it needs an update
@@ -263,8 +310,8 @@ void loop(void)
263310
droppedFrames++;
264311
}
265312

266-
prevKeysPressed = keysPressed;
267-
keysPressed = 0;
313+
prevKeysState = keysState;
314+
keysState = 0;
268315
}
269316
else
270317
{
@@ -332,6 +379,8 @@ void loop(void)
332379
if (currentState->redraw)
333380
{
334381
display.fillDisplayBuffer();
382+
display.setCursor(0, 8);
383+
display.setTextColor(PET_BLACK);
335384
currentState->draw(&display);
336385
drawTimeAndBattery();
337386
dirtyFrameBuffer = true;
@@ -472,7 +521,7 @@ int32_t msc_read_cb(uint32_t lba, void *buffer, uint32_t bufsize)
472521
{
473522
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
474523
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
475-
return flash.readBlocks(lba, (uint8_t *)buffer, bufsize / 512) ? bufsize : -1;
524+
return g::g_flash->readBlocks(lba, (uint8_t *)buffer, bufsize / 512) ? bufsize : -1;
476525
}
477526

478527
// Callback invoked when received WRITE10 command.
@@ -483,15 +532,15 @@ int32_t msc_write_cb(uint32_t lba, uint8_t *buffer, uint32_t bufsize)
483532
// check_uf2_handover(buffer, bufsize, 4, 5, tag);
484533
// Note: SPIFLash Bock API: readBlocks/writeBlocks/syncBlocks
485534
// already include 4K sector caching internally. We don't need to cache it, yahhhh!!
486-
return flash.writeBlocks(lba, buffer, bufsize / 512) ? bufsize : -1;
535+
return g::g_flash->writeBlocks(lba, buffer, bufsize / 512) ? bufsize : -1;
487536
}
488537

489538
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
490539
// used to flush any pending cache.
491540
void msc_flush_cb(void)
492541
{
493542
// sync with flash
494-
flash.syncBlocks();
543+
g::g_flash->syncBlocks();
495544

496545
// clear file system's cache to force refresh
497546
g::g_fatfs->cacheClear();

src/global.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
namespace g
77
{
88
FatFileSystem *g_fatfs;
9+
Adafruit_SPIFlash* g_flash;
10+
911
GraphicCache *g_cache;
1012
uint32_t g_keyReleased;
1113
uint32_t g_keyPressed;
14+
uint32_t g_keyHeld;
1215
stats g_stats;
1316
RTCZero g_rtc;
1417
} // namespace g

src/global.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
#pragma once
2+
#include "lib/RTCZero.h"
23
#include <Arduino.h>
3-
#include <RTCZero.h>
4+
#include <Adafruit_SPIFlash.h>
5+
46
/**
57
* Global objects and constants
68
*
@@ -38,7 +40,9 @@ extern FatFileSystem *g_fatfs;
3840
extern GraphicCache *g_cache;
3941
extern RTCZero g_rtc;
4042
extern stats g_stats;
43+
extern Adafruit_SPIFlash *g_flash;
4144

4245
extern uint32_t g_keyReleased;
4346
extern uint32_t g_keyPressed;
47+
extern uint32_t g_keyHeld;
4448
} // namespace g

0 commit comments

Comments
 (0)