😺
【M5coreS3】自作DigitalForm
前回作成したButtonを用います
lib/Button/Button.h
#ifndef BUTTON_H
#define BUTTON_H
#include <Arduino.h>
#include <M5CoreS3.h>
#include <functional>
class Button {
public:
Button() = default;
Button(
const String& label,
int x, int y, int width, int height,
std::function<void()> onPressed,
uint32_t color = WHITE,
uint32_t textColor = BLACK,
uint8_t textSize = 1,
bool autoDraw = true
);
void draw() const;
bool isPressed(int touchX, int touchY);
void update();
private:
String label;
int x = 0, y = 0, width = 0, height = 0;
uint32_t color = WHITE, textColor = BLACK;
std::function<void()> onPressed;
unsigned long pressTime = 0;
bool isHighlighted = false;
uint8_t textSize = 1;
bool autoDrawEnabled = true;
};
#endif // BUTTON_H
lib/Button/Button.cpp
#include "Button.h"
Button::Button(
const String& label,
int x, int y, int width, int height,
std::function<void()> onPressed,
uint32_t color,
uint32_t textColor,
uint8_t textSize,
bool autoDraw
) : label(label), x(x), y(y), width(width), height(height),
onPressed(onPressed), color(color), textColor(textColor),
textSize(textSize), autoDrawEnabled(autoDraw)
{
if (autoDrawEnabled) {
draw();
}
}
void Button::draw() const {
int32_t colorValue = isHighlighted? color : ((color & 0xFF000000) | (~color & 0x00FFFFFF));
CoreS3.Display.fillRect(x, y, width, height, colorValue);
CoreS3.Display.drawRect(x, y, width, height, colorValue);
int32_t textColorValue = isHighlighted? textColor : ((textColor & 0xFF000000) | (~textColor & 0x00FFFFFF));
CoreS3.Display.setTextSize(textSize);
CoreS3.Display.setTextColor(textColorValue);
CoreS3.Display.setTextDatum(MC_DATUM);
CoreS3.Display.drawString(label, x + width / 2, y + height / 2);
}
bool Button::isPressed(int touchX, int touchY) {
bool pressed = (touchX >= x && touchX < x + width &&
touchY >= y && touchY < y + height);
if (pressed && !isHighlighted) {
isHighlighted = true;
pressTime = millis();
draw();
if (onPressed) {
onPressed();
}
}
return pressed;
}
void Button::update() {
if (isHighlighted && millis() - pressTime > 200) {
isHighlighted = false;
draw();
}
}
これをmain.cppで引用します。
main.cpp
#include <M5CoreS3.h>
#include <M5Unified.h>
#include <optional>
#include "Button.h"
const int MAX_DIGITS = 8;
char inputNumber[MAX_DIGITS + 1] = {0}; // +1 for null terminator
int currentDigit = 0;
int cursorBlinkState = 0;
unsigned long lastBlinkTime = 0;
int prevMillis = 0;
const int displayWidth = 320;
const int displayHeight = 240;
//////////////////// digitalDisplay ////////////////////
const int digitalDisplayStartY = 30;
const int digitalDisplayMarginX = 10;
const int digitalDisplayPadding = 5;
const int charWidth = 18; // 固定幅フォントの文字高さ
const int digitalDisplayWidth = displayWidth - digitalDisplayMarginX * 2;
const int digitalDisplayHeight = 28 + digitalDisplayPadding * 2;
const int stringStartX = digitalDisplayMarginX + digitalDisplayPadding;
const int stringStartY = digitalDisplayStartY + digitalDisplayPadding;
void drawDigitalDisplay() {
CoreS3.Display.fillRect(digitalDisplayMarginX, digitalDisplayStartY, digitalDisplayWidth, digitalDisplayHeight, BLACK);
CoreS3.Display.drawRect(digitalDisplayMarginX, digitalDisplayStartY, digitalDisplayWidth, digitalDisplayHeight, WHITE);
}
void updateDisplay() {
drawDigitalDisplay();
CoreS3.Display.setTextColor(WHITE);
CoreS3.Display.setTextSize(1);
CoreS3.Display.setTextDatum(TL_DATUM);
CoreS3.Display.drawString(inputNumber, stringStartX, stringStartY);
}
void blinkCursor() {
if (millis() - lastBlinkTime > 500) {
cursorBlinkState = !cursorBlinkState;
lastBlinkTime = millis();
int cursorX = stringStartX + currentDigit * 20; // Adjust based on your font size
CoreS3.Display.fillRect(cursorX, stringStartY, 20, 30, cursorBlinkState ? WHITE : BLACK);
}
}
//////////////////// テンキーに関するプロパティ、メソッド ////////////////////
const int startY = displayHeight / 2 - 40;
const int spacing = 10;
const int btnWidth = (displayWidth - spacing * 6) / 5;
const int btnHeight = btnWidth-5;
Button buttons[12]; // 0-9, delete, enter
void buttonCallback(int num) {
if (num >= 0 && num <= 9) {
if (currentDigit < MAX_DIGITS) {
inputNumber[currentDigit++] = '0' + num;
inputNumber[currentDigit] = '\0';
updateDisplay();
}
} else if (num == 10) { // delete
if (currentDigit > 0) {
inputNumber[--currentDigit] = '\0';
updateDisplay();
}
} else if (num == 11) { // enter
// Enter処理をここに追加
Serial.println("Enter pressed");
}
}
void initializeButtons() {
for (int i = 0; i < 10; i++) {
int x = spacing + (i % 5) * (btnWidth + spacing);
int y = startY + (i / 5) * (btnHeight + spacing);
String label = String((i == 9) ? 0 : i + 1);
buttons[i] = Button(
label,
x, y, btnWidth, btnHeight,
[i]() { buttonCallback(i == 9 ? 0 : i + 1); },
WHITE,
BLACK,
1
);
}
const int controlKeyWidth = (CoreS3.Display.width() - 3 * spacing) / 2;
const int controlKeyStartY = startY + 2 * (btnHeight + spacing);
buttons[10] = Button("delete", spacing, controlKeyStartY, controlKeyWidth, btnHeight,
[]() { buttonCallback(10); }, WHITE, BLACK);
buttons[11] = Button("enter", spacing * 2 + controlKeyWidth, controlKeyStartY, controlKeyWidth, btnHeight,
[]() { buttonCallback(11); }, WHITE, BLACK);
}
void drawKeypad() {
for (int i = 0; i < 12; i++) {
buttons[i].draw();
}
}
void handleTouch() {
auto t = CoreS3.Touch.getDetail();
if (t.isPressed()) {
for (int i = 0; i < 12; i++) {
if (buttons[i].isPressed(t.x, t.y)) {
break; // ボタンが押されたら処理を終了
}
}
}
}
void handleButton(){
int curMillis = millis();
Serial.println(curMillis - prevMillis);
if(curMillis - prevMillis > 200){
prevMillis = curMillis ;
return;
}
Serial.println("aaaa");
}
void setup(void) {
Serial.begin(115200);
auto cfg = M5.config();
CoreS3.begin(cfg);
CoreS3.Display.setTextColor(RED);
CoreS3.Display.setTextDatum(middle_center);
CoreS3.Display.setFont(&fonts::Orbitron_Light_24);
CoreS3.Display.setTextSize(1);
initializeButtons();
drawDigitalDisplay();
drawKeypad();
}
void loop(void) {
CoreS3.update();
handleTouch();
blinkCursor();
M5.update();
if(M5.BtnB.isPressed()){
handleButton();
}
for (int i = 0; i < 12; i++) {
buttons[i].update();
}
}
補足
cores3 SEではcore2 basicにあった物理的なボタンは無く、<< ○ >>のタッチボタンになっていますが、
ライブラリのM5.BtnA、M5.BtnB、M5.BtnCでハンドリングできます。
改造版
#include <M5CoreS3.h>
#include <M5Unified.h>
#include <optional>
#include "Button.h"
const int MAX_DIGITS = 8;
char inputNumber[MAX_DIGITS + 1] = {0}; // +1 for null terminator
int currentDigit = 0;
int cursorBlinkState = 0;
unsigned long lastBlinkTime = 0;
int prevMillis = 0;
const int displayWidth = 320;
const int displayHeight = 240;
//////////////////// digitalDisplay ////////////////////
const int digitalDisplayStartY = 40;
const int digitalDisplayMarginX = 10;
const int digitalDisplayPadding = 5;
const int charWidth = 18; // 固定幅フォントの文字高さ
const int digitalDisplayWidth = displayWidth - digitalDisplayMarginX * 2;
const int digitalDisplayHeight = 28 + digitalDisplayPadding * 2;
const int stringStartX = digitalDisplayMarginX + digitalDisplayPadding;
const int stringStartY = digitalDisplayStartY + digitalDisplayPadding;
void drawDigitalDisplay() {
CoreS3.Display.fillRect(digitalDisplayMarginX, digitalDisplayStartY, digitalDisplayWidth, digitalDisplayHeight, BLACK);
CoreS3.Display.drawRect(digitalDisplayMarginX, digitalDisplayStartY, digitalDisplayWidth, digitalDisplayHeight, WHITE);
}
void updateDisplay() {
drawDigitalDisplay();
CoreS3.Display.setTextColor(WHITE);
CoreS3.Display.setTextSize(1);
CoreS3.Display.setTextDatum(TL_DATUM);
CoreS3.Display.drawString(inputNumber, stringStartX, stringStartY);
}
void blinkCursor() {
if (millis() - lastBlinkTime > 500) {
cursorBlinkState = !cursorBlinkState;
lastBlinkTime = millis();
int cursorX = stringStartX + currentDigit * 20; // Adjust based on your font size
CoreS3.Display.fillRect(cursorX, stringStartY, 20, 30, cursorBlinkState ? WHITE : BLACK);
}
}
//////////////////// テンキーに関するプロパティ、メソッド ////////////////////
const int btnStartY = 100;
const int btnSpacing = 5;
const int btnWidth = 70;
const int btnHeight = 40;
Button buttons[13]; // 0-9, delete, enter
void buttonCallback(int num) {
if (num >= 0 && num <= 10) {
if (currentDigit < MAX_DIGITS) {
inputNumber[currentDigit++] = '0' + num;
inputNumber[currentDigit] = '\0';
updateDisplay();
}
} else if (num == 11) { // delete
if (currentDigit > 0) {
inputNumber[--currentDigit] = '\0';
updateDisplay();
}
} else if (num == 12){ //enter
// if (currentDigit > 0) {
updateDisplay();
// }
}
}
void initializeButtons() {
for (int i = 0; i < 9; i++) {
int x = btnSpacing + (i % 3) * (btnWidth + btnSpacing);
int y = btnStartY + (i / 3) * (btnHeight + btnSpacing);
String label = String (i + 1);
buttons[i] = Button(
label,
x, y, btnWidth, btnHeight,
[i]() { buttonCallback(i + 1); },
WHITE,
BLACK,
1
);
}
int leftBtnStartX = btnWidth * 3 + btnSpacing * 4;
buttons[10] = Button("0", leftBtnStartX, btnStartY + (btnHeight + btnSpacing) * 2, btnWidth, btnHeight,
[]() { buttonCallback(10); }, WHITE, BLACK);
buttons[11] = Button("del", leftBtnStartX, btnStartY + (btnHeight + btnSpacing) * 0, btnWidth, btnHeight,
[]() { buttonCallback(11); }, WHITE, BLACK);
buttons[12] = Button("ent", leftBtnStartX, btnStartY + (btnHeight + btnSpacing) * 1, btnWidth, btnHeight,
[]() { buttonCallback(12); }, WHITE, BLACK);
}
void drawKeypad() {
for (int i = 0; i < 12; i++) {
buttons[i].draw();
}
}
void handleTouch() {
auto t = CoreS3.Touch.getDetail();
if (t.isPressed()) {
for (int i = 0; i < 12; i++) {
if (buttons[i].isPressed(t.x, t.y)) {
break; // ボタンが押されたら処理を終了
}
}
}
}
void handleButton(){
int curMillis = millis();
Serial.println(curMillis - prevMillis);
if(curMillis - prevMillis > 200){
prevMillis = curMillis ;
return;
}
Serial.println("aaaa");
}
void setup(void) {
Serial.begin(115200);
auto cfg = M5.config();
CoreS3.begin(cfg);
CoreS3.Display.setTextColor(RED);
CoreS3.Display.setTextDatum(middle_center);
CoreS3.Display.setFont(&fonts::Orbitron_Light_24);
CoreS3.Display.setTextSize(1);
initializeButtons();
drawDigitalDisplay();
drawKeypad();
}
void loop(void) {
CoreS3.update(); // タッチスクリーンの状態更新
handleTouch();
blinkCursor();
M5.update(); // 固定ボタンの状態更新
if(M5.BtnB.isPressed()){
handleButton();
}
for (int i = 0; i < 12; i++) {
buttons[i].update();
}
}
Discussion