Compare commits
1 Commits
08-74HC595
...
8303ea9d10
| Author | SHA1 | Date | |
|---|---|---|---|
|
8303ea9d10
|
BIN
06-joystick/joystickdemo.fzz
Normal file
BIN
06-joystick/joystickdemo.fzz
Normal file
Binary file not shown.
21
08-74HC595-Snake/.gdbinit
Normal file
21
08-74HC595-Snake/.gdbinit
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# 1. Connect to the running OpenOCD server
|
||||||
|
target remote :3333
|
||||||
|
|
||||||
|
# 2. Configure GDB for Espressif-specific environments
|
||||||
|
set remote hardware-watchpoint-limit 2
|
||||||
|
set remote hardware-breakpoint-limit 2
|
||||||
|
set mem inaccessible-by-default off
|
||||||
|
|
||||||
|
# 3. Handle FreeRTOS multi-threading without crashing GDB
|
||||||
|
handle SIGTRAP noprint nostop pass
|
||||||
|
|
||||||
|
# 4. Define a custom macro to safely reset the ESP32-S3
|
||||||
|
define reset
|
||||||
|
monitor reset halt
|
||||||
|
flushregs
|
||||||
|
end
|
||||||
|
|
||||||
|
# 5. Execute a fresh reset and set initial breakpoint
|
||||||
|
reset
|
||||||
|
thbreak setup
|
||||||
|
continue
|
||||||
74
08-74HC595-Snake/08-74HC595-Snake.ino
Normal file
74
08-74HC595-Snake/08-74HC595-Snake.ino
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include "controls.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Need 11 GPIO pins
|
||||||
|
- 74HC95 for the 8 segment
|
||||||
|
- 74HC595 for the rows of the 8x8
|
||||||
|
- 74HC9 for the cols of the 8x8
|
||||||
|
- 1x for the Joystick button
|
||||||
|
- 1x for the buzzer
|
||||||
|
Need 3 ADC pins
|
||||||
|
- Joy X
|
||||||
|
- Joy Y
|
||||||
|
- Difficulty potentiometer
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Pins 1 and 2 are on ADC channel 0 and 1.
|
||||||
|
#define PIN_JOY_X 1
|
||||||
|
#define PIN_JOY_Y 2
|
||||||
|
// Pin 47 is GPIO only
|
||||||
|
#define PIN_JOY_Z 47
|
||||||
|
|
||||||
|
// We save 4 pins by updating all 3 shift registers at once
|
||||||
|
// with one clock and one update signal. Each shift register
|
||||||
|
// only needs its own data line.
|
||||||
|
#define PIN_74HC595_CLOCK 11
|
||||||
|
#define PIN_74HC595_UPDATE 12
|
||||||
|
|
||||||
|
#define PIN_74HC595_LEDROWS_DATA 18
|
||||||
|
#define PIN_74HC595_LEDCOLS_DATA 13
|
||||||
|
#define PIN_74HC595_SCOREBOARD_DATA 14
|
||||||
|
|
||||||
|
#define PIN_BUZZER 21
|
||||||
|
|
||||||
|
#define PIN_DIFFICULTY 9
|
||||||
|
|
||||||
|
#define PWM_FREQUENCY 1000
|
||||||
|
#define PWM_BITWIDTH 12
|
||||||
|
|
||||||
|
Joystick js;
|
||||||
|
|
||||||
|
void initSerial()
|
||||||
|
{
|
||||||
|
Serial.begin(115200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
memset(&js, 0x00, sizeof(Joystick));
|
||||||
|
|
||||||
|
initSerial();
|
||||||
|
if ( initJoystick(&js, PIN_JOY_X, PIN_JOY_Y, PIN_JOY_Z) != ERRNO_SUCCESS ) {
|
||||||
|
Serial.printf("Failed to initialized Joystick datastructure : %d\n", errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if ( readButton(&js.button) != ERRNO_SUCCESS ) Serial.printf("Failed to read calibration button : %d\n", errno);
|
||||||
|
if ( js.button.state == BUTTON_STATE_DOWN && js.state != JOYSTICK_STATE_CALIBRATING ) {
|
||||||
|
js.button.state = BUTTON_STATE_HELD;
|
||||||
|
js.state = JOYSTICK_STATE_CALIBRATING;
|
||||||
|
}
|
||||||
|
if ( js.state == JOYSTICK_STATE_CALIBRATING ) {
|
||||||
|
if ( calibrateJoystick(&js) != ERRNO_SUCCESS ) {
|
||||||
|
Serial.printf("Failed to calibrate joystick : %d\n", errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( ( js.state & JOYSTICK_STATE_CALIBRATED) == JOYSTICK_STATE_CALIBRATED ) {
|
||||||
|
if ( readJoystick(&js) != ERRNO_SUCCESS ) {
|
||||||
|
Serial.printf("Failed to read joystick state : %d\n", errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
211
08-74HC595-Snake/README.md
Normal file
211
08-74HC595-Snake/README.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# Breadboard
|
||||||
|
|
||||||
|
This project uses 3 74HC595 serial to parallel shift registers, a 7-segment display multi unit, an 8x8 LED matrix, an active buzzer, an NPN transistor, a joystick, a handful of resistors and a potentiometer to make a playable Snake game.
|
||||||
|
|
||||||
|
# Lessons Learned
|
||||||
|
|
||||||
|
* Compiling, uploading, and debugging Arduino code from the CLI
|
||||||
|
* Managing mutexes in Arduino to handle thread locking
|
||||||
|
* How to write data to a 74HC595 shift register without using the Arduino HAL
|
||||||
|
* How to drive a 7-segment display
|
||||||
|
* How to drive an 8x8 LED matrix
|
||||||
|
* You don't need lots of pixels, or even colors, to make it fun
|
||||||
|
|
||||||
|
## Compiling, uploading, and debugging from the CLI
|
||||||
|
|
||||||
|
The Arduino IDE is ... not great. Its editor is crummy; I edit my code in Emacs and just use the IDE to upload, monitor and debug it. And frankly its debugger is not that great - I find most GUI debuggers to be kind of clunky, and this one especially. It's great for finding and adding libraries and things like that, but I don't like being constrained inside of it. Luckily the IDE is mostly just calling `arduino-cli` behind the scenes so everything the IDE does, we can do from the CLI. Setting up the arduino-cli is reasonably simple, but it quickly falls apart when you want to start debugging.
|
||||||
|
|
||||||
|
To set up the ESP32S3 dev board:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ arduino-cli core update-index \
|
||||||
|
--additional-urls https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||||
|
$ arduino-cli core install esp32:esp32 \
|
||||||
|
--additional-urls https://espressif.github.io/arduino-esp32/package_esp32_index.json
|
||||||
|
$ arduino-cli board list
|
||||||
|
Port Protocol Type Board Name FQBN Core
|
||||||
|
/dev/ttyACM0 serial Serial Port (USB) Unknown
|
||||||
|
```
|
||||||
|
|
||||||
|
To attach to the dev board when it's connected over USB Serial
|
||||||
|
|
||||||
|
```
|
||||||
|
# Get the board FQBN from the board list
|
||||||
|
$ arduino-cli board list all esp32
|
||||||
|
$ arduino-cli board attach -b esp32:esp32:esp32s3 -p serial:///dev/ttyACM0 .
|
||||||
|
```
|
||||||
|
|
||||||
|
To compile a project in the current directory
|
||||||
|
|
||||||
|
```
|
||||||
|
arduino-cli compile -b esp32:esp32:esp32s3 .
|
||||||
|
```
|
||||||
|
|
||||||
|
.. Then watch lots and lots of errors because the Arduino IDE has hidden the knowledge of header files and compiler flags from you.
|
||||||
|
|
||||||
|
* Apparently `.ino` files are magic, and get a bunch of stuff added to them for free, like the correct header files (like `Arduino.h`) for whatever you're using.
|
||||||
|
* Beware the fact that Arduino is C++ by default - if you make a `.c` file and expect to be able to call `Serial.xxx()`, that's not gonna work. Your code has to be `.cpp` files, like it or not.
|
||||||
|
* Your board has hidden compile options that you're used to setting in the Arduino IDE. For example USB CDC on boot options. If you don't set this at all, you'll get mysterious errors about Serial missing, etc. You need to inspect the board parameters and pass them to your build command appropriately.
|
||||||
|
* You don't get to control the link order on the output files.
|
||||||
|
* If you don't specify the output directory, it goes to some cache directory off in the middle of nowhere
|
||||||
|
|
||||||
|
```
|
||||||
|
$ mkdir -p build
|
||||||
|
|
||||||
|
$ arduino-cli compile --fqbn esp32:esp32:esp32s3:CDCOnBoot=cdc --output-dir build/ .
|
||||||
|
Sketch uses 320680 bytes (24%) of program storage space. Maximum is 1310720 bytes.
|
||||||
|
Global variables use 22504 bytes (6%) of dynamic memory, leaving 305176 bytes for local variables. Maximum is 327680 bytes.
|
||||||
|
|
||||||
|
$ ls build/
|
||||||
|
08-74HC595-Snake.ino.bin 08-74HC595-Snake.ino.elf 08-74HC595-Snake.ino.merged.bin esp32.esp32.esp32s3
|
||||||
|
08-74HC595-Snake.ino.bootloader.bin 08-74HC595-Snake.ino.map 08-74HC595-Snake.ino.partitions.bin
|
||||||
|
```
|
||||||
|
|
||||||
|
Sweet. Now to upload it
|
||||||
|
|
||||||
|
```
|
||||||
|
$ arduino-cli upload -p /dev/ttyACM0 -b esp32:esp32:esp32s3:CDCOnBoot=cdc --build-path build/
|
||||||
|
esptool v5.3.0
|
||||||
|
Serial port /dev/ttyACM0:
|
||||||
|
Connecting....
|
||||||
|
Connected to ESP32-S3 on /dev/ttyACM0:
|
||||||
|
Chip type: ESP32-S3 (QFN56) (revision v0.2)
|
||||||
|
Features: Wi-Fi, BT 5 (LE), Dual Core + LP Core, 240MHz, Embedded PSRAM 8MB (AP_3v3)
|
||||||
|
Crystal frequency: 40MHz
|
||||||
|
MAC: 1c:db:d4:59:f8:c4
|
||||||
|
|
||||||
|
Uploading stub flasher...
|
||||||
|
|
||||||
|
.... snip ...
|
||||||
|
Verifying written data...
|
||||||
|
Hash of data verified.
|
||||||
|
|
||||||
|
Hard resetting via RTS pin...
|
||||||
|
New upload port: /dev/ttyACM0 (serial)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now let's monitor the serial:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ arduino-cli monitor -p /dev/ttyACM0
|
||||||
|
Using default monitor configuration for board: esp32:esp32:esp32s3
|
||||||
|
Monitor port settings:
|
||||||
|
baudrate=9600
|
||||||
|
bits=8
|
||||||
|
dtr=on
|
||||||
|
parity=none
|
||||||
|
rts=on
|
||||||
|
stop_bits=1
|
||||||
|
|
||||||
|
Connecting to /dev/ttyACM0. Press CTRL-C to exit.
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's debug it. The process requires spinning up OpenOCD and connecting GDB to it. Figuring out where OpenOCD got installed is not necessarily straightforward ... it depends on your toolchain, version, etc ... There is some googling involved. But once you find it:
|
||||||
|
|
||||||
|
```
|
||||||
|
cd ~/.arduino15/packages/esp32/tools/openocd-esp32/v0.12.0-esp32-20251215/share/openocd/scripts/
|
||||||
|
../../../bin/openocd -f interface/esp_usb_jtag.cfg -f target/esp32s3.cfg
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can connect gdb to it. I use a `.gdbinit` file to help set up GDB for monitoring this specific hardware environment, doing things like mapping a custom reset function:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ cat .gdbinit
|
||||||
|
# 1. Connect to the running OpenOCD server
|
||||||
|
target remote :3333
|
||||||
|
|
||||||
|
# 2. Configure GDB for Espressif-specific environments
|
||||||
|
set remote hardware-watchpoint-limit 2
|
||||||
|
set remote hardware-breakpoint-limit 2
|
||||||
|
set mem inaccessible-by-default off
|
||||||
|
|
||||||
|
# 3. Handle FreeRTOS multi-threading without crashing GDB
|
||||||
|
handle SIGTRAP noprint nostop pass
|
||||||
|
|
||||||
|
# 4. Define a custom macro to safely reset the ESP32-S3
|
||||||
|
define reset
|
||||||
|
monitor reset halt
|
||||||
|
flushregs
|
||||||
|
end
|
||||||
|
|
||||||
|
# 5. Execute a fresh reset and set initial breakpoint
|
||||||
|
reset
|
||||||
|
thbreak setup
|
||||||
|
continue
|
||||||
|
```
|
||||||
|
|
||||||
|
<center><img alt="This is where we would run the debugger, if we had one" src="nodebugger.jpeg" width="320px"/></center>
|
||||||
|
|
||||||
|
This is where it gets quite silly. Apparently the esp32 toolchain installed by `arduino-cli` doesn't include the debugger. (Who would want a silly thing like that?) So you have to actually download and install the esp32 toolchain from Espressif directly, make sure that the gcc version matches, and then just drop in the debugger from that toolchain.
|
||||||
|
|
||||||
|
I'm sure there won't ever be any problems at all from mixing and matching like this.
|
||||||
|
|
||||||
|
So I had to ...
|
||||||
|
|
||||||
|
1. Install the Espressif EIM tool directly from Espressif via Apt
|
||||||
|
2. Install the ESP-IDF via the Espressif EIM tool
|
||||||
|
3. ... wait ... watch my disk space get consumed by duplicate dev tools ...
|
||||||
|
4. Source the ESP-IDF environment variables into my terminal `source "/home/andrew/.espressif/tools/activate_idf_v6.0.1.sh"`
|
||||||
|
5. Run the debugger against openocd
|
||||||
|
|
||||||
|
... And it works
|
||||||
|
|
||||||
|
```
|
||||||
|
Hardware assisted breakpoint 1 at 0x42001f3f: file /home/andrew/source/source.starfort.tech/andrew/esp32-learning/08-74HC595-Snake/08-74HC595-Snake.ino, line 49.
|
||||||
|
Info : [esp32s3.cpu0] Target halted, PC=0x42008890, debug_reason=00000000
|
||||||
|
[esp32s3.cpu0] Target halted, PC=0x42008890, debug_reason=00000000Info : Set GDB target to 'esp32s3.cpu0'
|
||||||
|
|
||||||
|
Set GDB target to 'esp32s3.cpu0'
|
||||||
|
Info : [esp32s3.cpu1] Target halted, PC=0x42001F3F, debug_reason=00000001
|
||||||
|
[esp32s3.cpu1] Target halted, PC=0x42001F3F, debug_reason=00000001
|
||||||
|
Info : Detected FreeRTOS version: (10.5.1)
|
||||||
|
[New Thread 1070529176]
|
||||||
|
[Remote target exited]
|
||||||
|
[New Thread 1070202636]
|
||||||
|
[New Thread 1070204132]
|
||||||
|
[New Thread 1070185320]
|
||||||
|
[New Thread 1070207644]
|
||||||
|
[New Thread 1070194980]
|
||||||
|
[New Thread 1070183888]
|
||||||
|
[Switching to Thread 1070529176]
|
||||||
|
|
||||||
|
Thread 2 "loopTask" hit Temporary breakpoint 1, setup ()
|
||||||
|
at /home/andrew/source/source.starfort.tech/andrew/esp32-learning/08-74HC595-Snake/08-74HC595-Snake.ino:49
|
||||||
|
49 memset(&js, 0x00, sizeof(Joystick));
|
||||||
|
(gdb)
|
||||||
|
```
|
||||||
|
|
||||||
|
Nevermind that the arduino-cli is compiling with a 14.x version of the esp32 gcc and this toolchain I just installed is using 16.x. .... You know what it's fine. Don't worry about it.
|
||||||
|
|
||||||
|
This kind of garbage is apparently just part and parcel of working in the embedded world. When I get into STM32 and PIC microcontrollers here in a bit, I'll wind up with even more toolchains strung about and connected together with other various glue. I'm not entirely unfamiliar with this - back when I was at Nintendo, rigging up software for the devkits involved spaghetti library version and application management of the highest order. It wasn't until right about the time tht I left that we finally got with SDSG and got a working tool to manage all of that mess in a somewhat reasonable manner.
|
||||||
|
|
||||||
|
This just means that I'll continue using the Arduino IDE to debug my code; I can do everything else safely from the command line.
|
||||||
|
|
||||||
|
## Custom 74HC595 driver code
|
||||||
|
|
||||||
|
* Getting the Arduino code to compile the additional .c file and include the header
|
||||||
|
* Managing the clock signal
|
||||||
|
|
||||||
|
## Driving 7-segment displays
|
||||||
|
|
||||||
|
* Single units
|
||||||
|
* Multiple units
|
||||||
|
|
||||||
|
## Driving an 8x8 LED matrix
|
||||||
|
|
||||||
|
* Treat it like a tiny framebuffer. 64 (8*8) bytes, each containing a packed bitfield.
|
||||||
|
* High nibble
|
||||||
|
* On / Off
|
||||||
|
* Is it a pellet or a snake part
|
||||||
|
* Low nibble
|
||||||
|
* How many game cycles should this stay lit. For snake parts, this is a counter. For pellets this is ignored.
|
||||||
|
|
||||||
|
## Fun within constraints
|
||||||
|
|
||||||
|
* Only 1 color
|
||||||
|
* Only 64 possible pixels
|
||||||
|
* Four 7 segment readouts
|
||||||
|
* Only 1 sound
|
||||||
|
* Only 1 button
|
||||||
|
* One player
|
||||||
|
* 1 difficulty adjuster (controls the speed of the game clock)
|
||||||
4
08-74HC595-Snake/build.sh
Normal file
4
08-74HC595-Snake/build.sh
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
arduino-cli compile --fqbn esp32:esp32:esp32s3:CDCOnBoot=cdc --output-dir build/ .
|
||||||
|
|
||||||
154
08-74HC595-Snake/controls.cpp
Normal file
154
08-74HC595-Snake/controls.cpp
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "controls.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
|
// For initializing B103-348 style joysticks
|
||||||
|
int initJoystick(Joystick *js, uint8_t pin_x, uint8_t pin_y, uint8_t pin_z)
|
||||||
|
{
|
||||||
|
if ( js == NULL ) {
|
||||||
|
ERROR(ERRNO_NULLPOINTER);
|
||||||
|
}
|
||||||
|
js->button.pin = pin_z;
|
||||||
|
js->button.debouncetime = BUTTON_STABLETIME;
|
||||||
|
js->button.pressedvalue = LOW;
|
||||||
|
pinMode(js->button.pin, INPUT_PULLUP);
|
||||||
|
js->x.pin = pin_x;
|
||||||
|
js->x.calibration.stable_time = JOYSTICK_STABLETIME;
|
||||||
|
js->y.pin = pin_y;
|
||||||
|
js->y.calibration.stable_time = JOYSTICK_STABLETIME;
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For initializing simple buttons
|
||||||
|
int initButton(Button *button)
|
||||||
|
{
|
||||||
|
pinMode(button->pin, INPUT);
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calibrate a given joystick
|
||||||
|
int calibrateJoystick(Joystick *js)
|
||||||
|
{
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t curmillis = 0;
|
||||||
|
if ( js == NULL ) {
|
||||||
|
ERROR(ERRNO_NULLPOINTER);
|
||||||
|
}
|
||||||
|
curmillis = millis();
|
||||||
|
if ( js->x.calibration.start_time == 0 || js->y.calibration.start_time == 0 ) {
|
||||||
|
// Starting a new calibration cycle
|
||||||
|
Serial.printf("Starting a new calibration cycle\n");
|
||||||
|
js->x.calibration.low = 65535;
|
||||||
|
js->x.calibration.high = 0;
|
||||||
|
js->y.calibration.low = 65535;
|
||||||
|
js->y.calibration.high = 0;
|
||||||
|
js->x.calibration.start_time = curmillis;
|
||||||
|
js->y.calibration.start_time = curmillis;
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
if ( (curmillis - js->x.calibration.start_time) >= js->x.calibration.stable_time ) {
|
||||||
|
js->state = JOYSTICK_STATE_CALIBRATED;
|
||||||
|
js->x.calibration.start_time = 0;
|
||||||
|
js->y.calibration.start_time = 0;
|
||||||
|
Serial.printf("Calibrated joystick to x: <%d, %d> y <%d, %d>\n",
|
||||||
|
js->x.calibration.low,
|
||||||
|
js->x.calibration.high,
|
||||||
|
js->y.calibration.low,
|
||||||
|
js->y.calibration.high);
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
x = analogRead(js->x.pin);
|
||||||
|
if ( x < js->x.calibration.low ) {
|
||||||
|
js->x.calibration.low = x;
|
||||||
|
} else if ( x > js->x.calibration.high ) {
|
||||||
|
js->x.calibration.high = x;
|
||||||
|
}
|
||||||
|
y = analogRead(js->y.pin);
|
||||||
|
if ( y < js->y.calibration.low ) {
|
||||||
|
js->y.calibration.low = y;
|
||||||
|
} else if ( y > js->y.calibration.high ) {
|
||||||
|
js->y.calibration.high = y;
|
||||||
|
}
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the state of a given button
|
||||||
|
int readButton(Button *button)
|
||||||
|
{
|
||||||
|
uint32_t pinvalue;
|
||||||
|
uint32_t curmillis;
|
||||||
|
uint32_t buttonvalue;
|
||||||
|
if ( button == NULL ) {
|
||||||
|
ERROR(ERRNO_NULLPOINTER);
|
||||||
|
}
|
||||||
|
curmillis = millis();
|
||||||
|
buttonvalue = digitalRead(button->pin);
|
||||||
|
if ( (button->state & BUTTON_STATE_BOUNCING) == BUTTON_STATE_BOUNCING ) {
|
||||||
|
if ( (curmillis - button->debounce_start_time) >= button->debouncetime ) {
|
||||||
|
if ( buttonvalue == button->pressedvalue ) {
|
||||||
|
button->state = BUTTON_STATE_DOWN;
|
||||||
|
} else {
|
||||||
|
button->state = BUTTON_STATE_UP;
|
||||||
|
}
|
||||||
|
Serial.printf("Button on pin %d has debounced state %d\n", button->pin, button->state);
|
||||||
|
button->debounce_start_time = 0;
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
if ( buttonvalue != button->pressedvalue && (
|
||||||
|
(button->state & BUTTON_STATE_DOWN) == BUTTON_STATE_DOWN ||
|
||||||
|
(button->state & BUTTON_STATE_HELD) == BUTTON_STATE_HELD)){
|
||||||
|
// We are beginning to release. Debounce.
|
||||||
|
Serial.printf("Debouncing button on pin %d for release\n", button->pin);
|
||||||
|
button->state = button->state | BUTTON_STATE_BOUNCING;
|
||||||
|
button->debounce_start_time = curmillis;
|
||||||
|
}
|
||||||
|
if ( buttonvalue == button->pressedvalue && (
|
||||||
|
(button->state & BUTTON_STATE_DOWN) != BUTTON_STATE_DOWN &&
|
||||||
|
(button->state & BUTTON_STATE_HELD) != BUTTON_STATE_HELD)){
|
||||||
|
// We are beginning to press. Debounce.
|
||||||
|
Serial.printf("Debouncing button on pin %d for press\n", button->pin);
|
||||||
|
button->state = button->state | BUTTON_STATE_BOUNCING;
|
||||||
|
button->debounce_start_time = curmillis;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
int readJoystick(Joystick *js)
|
||||||
|
{
|
||||||
|
uint32_t adcvalue = 0;
|
||||||
|
if ( js == NULL ) {
|
||||||
|
ERROR(ERRNO_NULLPOINTER);
|
||||||
|
}
|
||||||
|
js->state = js->state | JOYSTICK_STATE_READING;
|
||||||
|
|
||||||
|
adcvalue = analogRead(js->x.pin);
|
||||||
|
if ( adcvalue < js->x.calibration.low || adcvalue > js->x.calibration.high ) {
|
||||||
|
js->x.position = adcvalue;
|
||||||
|
} else {
|
||||||
|
// Snap to center
|
||||||
|
js->x.position = 2048;
|
||||||
|
}
|
||||||
|
adcvalue = analogRead(js->y.pin);
|
||||||
|
if ( adcvalue < js->y.calibration.low || adcvalue > js->y.calibration.high ) {
|
||||||
|
js->y.position = adcvalue;
|
||||||
|
} else {
|
||||||
|
// Snap to center
|
||||||
|
js->y.position = 2048;
|
||||||
|
}
|
||||||
|
//Serial.printf("Joystick x %d y %d\n", js->x.position, js->y.position);
|
||||||
|
|
||||||
|
readButton(&js->button);
|
||||||
|
js->state = js->state ^ JOYSTICK_STATE_READING;
|
||||||
|
if ( errno != ERRNO_SUCCESS ) {
|
||||||
|
Serial.printf("Failed to read joystick button : %d\n", errno);
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
js->state = js->state | JOYSTICK_STATE_READY;
|
||||||
|
return ERRNO_SUCCESS;
|
||||||
|
}
|
||||||
72
08-74HC595-Snake/controls.h
Normal file
72
08-74HC595-Snake/controls.h
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
#ifndef _JOYSTICK_H_
|
||||||
|
#define _JOYSTICK_H_
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define BUTTON_STABLETIME 100
|
||||||
|
#define JOYSTICK_STABLETIME 3000
|
||||||
|
|
||||||
|
// Button states
|
||||||
|
#define BUTTON_STATE_BOUNCING (1 << 0)
|
||||||
|
#define BUTTON_STATE_DOWN (1 << 1)
|
||||||
|
#define BUTTON_STATE_UP (1 << 2)
|
||||||
|
#define BUTTON_STATE_HELD (1 << 3)
|
||||||
|
|
||||||
|
// Joystick states
|
||||||
|
#define JOYSTICK_STATE_CALIBRATING (1 << 0)
|
||||||
|
#define JOYSTICK_STATE_CALIBRATED (1 << 1)
|
||||||
|
#define JOYSTICK_STATE_READING (1 << 2)
|
||||||
|
#define JOYSTICK_STATE_READY (1 << 3)
|
||||||
|
|
||||||
|
typedef struct Calibration {
|
||||||
|
// When did calibration start
|
||||||
|
uint32_t start_time;
|
||||||
|
// Low calibration range
|
||||||
|
uint32_t low;
|
||||||
|
// High calibration range
|
||||||
|
uint32_t high;
|
||||||
|
// How long we should sample values on this joystick
|
||||||
|
uint32_t stable_time;
|
||||||
|
} Calibration;
|
||||||
|
|
||||||
|
typedef struct Button {
|
||||||
|
// What pin is this button on
|
||||||
|
uint8_t pin;
|
||||||
|
// What is the state of this button (bitmask of BUTTON_STATE_*)
|
||||||
|
uint8_t state;
|
||||||
|
// Is this button pressed when it is LOW or HIGH?
|
||||||
|
uint32_t pressedvalue;
|
||||||
|
// How long do we wait when debouncing this button
|
||||||
|
uint32_t debouncetime;
|
||||||
|
// When did we start debouncing
|
||||||
|
uint32_t debounce_start_time;
|
||||||
|
} Button;
|
||||||
|
|
||||||
|
typedef struct JoystickAxis {
|
||||||
|
// What ADC pin is this joystick axis connected to
|
||||||
|
uint8_t pin;
|
||||||
|
// Calibration data
|
||||||
|
Calibration calibration;
|
||||||
|
// Position as of the last read time.
|
||||||
|
uint32_t position;
|
||||||
|
} JoystickAxis;
|
||||||
|
|
||||||
|
typedef struct Joystick {
|
||||||
|
// X axis data
|
||||||
|
JoystickAxis x;
|
||||||
|
// Y axis data
|
||||||
|
JoystickAxis y;
|
||||||
|
// This is the Z axis switch on the joystick control
|
||||||
|
Button button;
|
||||||
|
// What is the state of this joystick (bitmask of JOYSTICK_STATE_*)
|
||||||
|
uint8_t state;
|
||||||
|
} Joystick;
|
||||||
|
|
||||||
|
int initJoystick(Joystick *js, uint8_t pin_x, uint8_t pin_y, uint8_t pin_z);
|
||||||
|
int initButton(Button *button);
|
||||||
|
int calibrateJoystick(Joystick *js);
|
||||||
|
int readButton(Button *button);
|
||||||
|
int readJoystick(Joystick *js);
|
||||||
|
|
||||||
|
#endif // _JOYSTICK_H_
|
||||||
BIN
08-74HC595-Snake/datasheets/3461BS.pdf
Normal file
BIN
08-74HC595-Snake/datasheets/3461BS.pdf
Normal file
Binary file not shown.
BIN
08-74HC595-Snake/datasheets/5161bs.pdf
Normal file
BIN
08-74HC595-Snake/datasheets/5161bs.pdf
Normal file
Binary file not shown.
BIN
08-74HC595-Snake/datasheets/sn74hc595.pdf
Normal file
BIN
08-74HC595-Snake/datasheets/sn74hc595.pdf
Normal file
Binary file not shown.
Binary file not shown.
8
08-74HC595-Snake/debug.sh
Normal file
8
08-74HC595-Snake/debug.sh
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
(cd ~/.arduino15/packages/esp32/tools/openocd-esp32/v0.12.0-esp32-20251215/share/openocd/scripts/ ; ../../../bin/openocd -f interface/esp_usb_jtag.cfg -f target/esp32s3.cfg) &
|
||||||
|
|
||||||
|
/home/andrew/.espressif/tools/xtensa-esp-elf-gdb/16.3_20250913/xtensa-esp-elf-gdb/bin/xtensa-esp32-elf-gdb -x .gdbinit ./build/08-74HC595-Snake.ino.elf
|
||||||
|
|
||||||
|
#/home/andrew/.arduino15/packages/esp32/tools/esp-x32/2601/share/licenses/binutils/gdb -x .gdbinit ./build/08-74HC595-Snake.ino.elf
|
||||||
|
|
||||||
1
08-74HC595-Snake/error.cpp
Normal file
1
08-74HC595-Snake/error.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
#include "error.h"
|
||||||
14
08-74HC595-Snake/error.h
Normal file
14
08-74HC595-Snake/error.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#ifndef _ERROR_H_
|
||||||
|
#define _ERROR_H_
|
||||||
|
|
||||||
|
#define ERRNO_SUCCESS 0
|
||||||
|
#define ERRNO_NULLPOINTER 1
|
||||||
|
#define ERRNO_IO 2
|
||||||
|
#define ERRNO_TIMEOUT 3
|
||||||
|
#define ERRNO_CALIBRATION 4
|
||||||
|
|
||||||
|
#define ERROR(x) errno=x; return x;
|
||||||
|
|
||||||
|
extern int errno;
|
||||||
|
|
||||||
|
#endif // _ERROR_H_
|
||||||
3
08-74HC595-Snake/monitor.sh
Normal file
3
08-74HC595-Snake/monitor.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
arduino-cli monitor -p /dev/ttyACM0
|
||||||
BIN
08-74HC595-Snake/nodebugger.jpeg
Normal file
BIN
08-74HC595-Snake/nodebugger.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 106 KiB |
2
08-74HC595-Snake/sketch.yaml
Normal file
2
08-74HC595-Snake/sketch.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
default_fqbn: esp32:esp32:esp32s3
|
||||||
|
default_port: serial:///dev/ttyACM0
|
||||||
3
08-74HC595-Snake/upload.sh
Normal file
3
08-74HC595-Snake/upload.sh
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
arduino-cli upload -p /dev/ttyACM0 -b esp32:esp32:esp32s3:CDCOnBoot=cdc --build-path build/
|
||||||
Reference in New Issue
Block a user