testing firmware on new Nano R4.

This commit is contained in:
2025-09-10 11:54:51 -07:00
parent acd028846c
commit c6ce5b1309
9 changed files with 484 additions and 57 deletions

118
examples/test_r4/encoder.h Normal file
View File

@ -0,0 +1,118 @@
/**
* @file encoder.h
* @author Adam Wonak (https://github.com/awonak)
* @brief Class for interacting with encoders.
* @version 2.0.0
* @date 2025-08-17
*
* @copyright MIT - (c) 2025 - Adam Wonak - adam.wonak@gmail.com
*
*/
#ifndef ENCODER_DIR_H
#define ENCODER_DIR_H
#include <RotaryEncoder.h>
#include "button.h"
#include "peripherials.h"
class Encoder {
protected:
typedef void (*CallbackFunction)(void);
typedef void (*RotateCallbackFunction)(int val);
CallbackFunction on_press;
RotateCallbackFunction on_press_rotate;
RotateCallbackFunction on_rotate;
int change;
public:
Encoder() : encoder_(ENCODER_PIN1, ENCODER_PIN2, RotaryEncoder::LatchMode::FOUR3),
button_(ENCODER_SW_PIN) {
_instance = this;
}
~Encoder() {}
// Set to true if the encoder read direction should be reversed.
void SetReverseDirection(bool reversed) {
reversed_ = reversed;
}
void AttachPressHandler(CallbackFunction f) {
on_press = f;
}
void AttachRotateHandler(RotateCallbackFunction f) {
on_rotate = f;
}
void AttachPressRotateHandler(RotateCallbackFunction f) {
on_press_rotate = f;
}
void Process() {
encoder_.tick();
// Get encoder position change amount.
int encoder_rotated = _rotate_change() != 0;
bool button_pressed = button_.On();
button_.Process();
// Handle encoder position change and button press.
if (button_pressed && encoder_rotated) {
rotated_while_held_ = true;
if (on_press_rotate != NULL) on_press_rotate(change);
} else if (!button_pressed && encoder_rotated) {
if (on_rotate != NULL) on_rotate(change);
} else if (button_.Change() == Button::CHANGE_RELEASED && !rotated_while_held_) {
if (on_press != NULL) on_press();
}
// Reset rotate while held state.
if (button_.Change() == Button::CHANGE_RELEASED && rotated_while_held_) {
rotated_while_held_ = false;
}
}
static void isr() {
// If the instance has been created, call its tick() method.
if (_instance) {
_instance->encoder_.tick();
}
}
private:
static Encoder* _instance;
int previous_pos_;
bool rotated_while_held_;
bool reversed_ = false;
RotaryEncoder encoder_;
Button button_;
// Return the number of ticks change since last polled.
int _rotate_change() {
int position = encoder_.getPosition();
unsigned long ms = encoder_.getMillisBetweenRotations();
// Validation (TODO: add debounce check).
if (previous_pos_ == position) {
return 0;
}
// Update state variables.
change = position - previous_pos_;
previous_pos_ = position;
// Encoder rotate acceleration.
if (ms < 16) {
change *= 3;
} else if (ms < 32) {
change *= 2;
}
if (reversed_) {
change = -(change);
}
return change;
}
};
#endif

View File

@ -0,0 +1,76 @@
#include "peripherials.h"
#include "encoder.h"
#include <U8g2lib.h>
U8G2_SSD1306_128X64_NONAME_1_HW_I2C display(U8G2_R2, SCL, SDA, U8X8_PIN_NONE);
Encoder encoder;
const int OUTPUT_COUNT = 6;
int outputs[OUTPUT_COUNT] = {
OUT_CH1,
OUT_CH2,
OUT_CH3,
OUT_CH4,
OUT_CH5,
OUT_CH6,
};
volatile int idx = 0;
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
for (int i = 0; i < OUTPUT_COUNT; i++) {
pinMode(outputs[i], OUTPUT);
}
encoder.AttachRotateHandler(rotateEncoder);
encoder.AttachPressHandler(press);
display.begin();
}
void rotateEncoder(int val) {
idx = (val > 0)
? constrain(idx + 1, 0 , OUTPUT_COUNT)
: constrain(idx - 1, 0 , OUTPUT_COUNT);
}
// the loop function runs over and over again forever
void loop() {
encoder.Process();
UpdateDisplay();
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(outputs[idx], HIGH); // turn the LED on (HIGH is the voltage level)
delay(500); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
digitalWrite(outputs[idx], LOW); // turn the LED on (LOW is the voltage level)
delay(500); // wait for a second
}
void press() {
for (int i = 0; i < OUTPUT_COUNT; i++) {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
digitalWrite(outputs[i], HIGH); // turn the LED on (HIGH is the voltage level)
delay(50); // wait for a second
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
digitalWrite(outputs[i], LOW); // turn the LED on (LOW is the voltage level)
delay(50);
}
}
void UpdateDisplay() {
display.firstPage();
do {
display.drawStr(0, 0, "Hello");
} while (display.nextPage());
}