Compare commits
7 Commits
771c135cd2
...
e2ea10152d
Author | SHA1 | Date |
---|---|---|
radex | e2ea10152d | |
radex | 8eae11c530 | |
radex | a4f9e1b55e | |
radex | 800998f759 | |
radex | 65dff1e504 | |
radex | 8da396e6fb | |
radex | 45f84c58ad |
|
@ -2,19 +2,12 @@
|
|||
#include "constants.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
void buzzOff() {
|
||||
noTone(BUZZER_PIN);
|
||||
pinMode(BUZZER_PIN, INPUT);
|
||||
}
|
||||
|
||||
void helloBuzz() {
|
||||
tone(BUZZER_PIN, 500, 100);
|
||||
delay(100);
|
||||
tone(BUZZER_PIN, 1000, 100);
|
||||
delay(100);
|
||||
tone(BUZZER_PIN, 4000, 100);
|
||||
delay(100);
|
||||
buzzOff();
|
||||
}
|
||||
|
||||
void happyBuzz() {
|
||||
|
@ -22,23 +15,18 @@ void happyBuzz() {
|
|||
delay(75);
|
||||
tone(BUZZER_PIN, 2000, 100);
|
||||
delay(100);
|
||||
buzzOff();
|
||||
}
|
||||
|
||||
void sadBuzz() {
|
||||
tone(BUZZER_PIN, 330, 250);
|
||||
delay(300);
|
||||
tone(BUZZER_PIN, 311, 250);
|
||||
delay(250);
|
||||
buzzOff();
|
||||
}
|
||||
|
||||
void beep() {
|
||||
tone(BUZZER_PIN, 1000, 50);
|
||||
delay(50);
|
||||
buzzOff();
|
||||
}
|
||||
|
||||
void tick() {
|
||||
tone(BUZZER_PIN, 200, 5);
|
||||
tone(BUZZER_PIN, 200, 10);
|
||||
}
|
||||
|
|
|
@ -4,5 +4,4 @@ void helloBuzz();
|
|||
void happyBuzz();
|
||||
void sadBuzz();
|
||||
void beep();
|
||||
void buzzOff();
|
||||
void tick();
|
||||
|
|
|
@ -24,3 +24,12 @@
|
|||
// --- Keyboard config
|
||||
|
||||
#define KBD_I2C_ADDR 0x21
|
||||
|
||||
// Used by keyboard and encoder switch
|
||||
#define DEBOUNCE_MS 10
|
||||
|
||||
// --- Z axis motor
|
||||
|
||||
#define STEPPER_ENABLE 8
|
||||
#define STEPPER_DIR 9
|
||||
#define STEPPER_STEP 10
|
||||
|
|
|
@ -13,8 +13,6 @@ When rotated clockwise, CLK changes before DT; when rotated counter-clockwise, D
|
|||
|
||||
*/
|
||||
|
||||
#define SW_DEBOUNCE_MS 10
|
||||
|
||||
bool previousClk = false;
|
||||
bool previousDt = false;
|
||||
|
||||
|
@ -40,8 +38,8 @@ SwitchEvent handleSwitch() {
|
|||
}
|
||||
|
||||
// debounce
|
||||
unsigned long now = millis();
|
||||
if (now - lastChangeAt < SW_DEBOUNCE_MS) {
|
||||
auto now = millis();
|
||||
if (now - lastChangeAt < DEBOUNCE_MS) {
|
||||
return SWITCH_NONE;
|
||||
}
|
||||
|
||||
|
@ -53,6 +51,8 @@ SwitchEvent handleSwitch() {
|
|||
return isPressed ? SWITCH_PRESSED : SWITCH_RELEASED;
|
||||
}
|
||||
|
||||
unsigned long lastEncoderChangeAt = 0;
|
||||
|
||||
EncoderEvent handleEncoder() {
|
||||
bool clk = digitalRead(CLK_PIN);
|
||||
bool dt = digitalRead(DT_PIN);
|
||||
|
@ -62,7 +62,11 @@ EncoderEvent handleEncoder() {
|
|||
return ENCODER_NONE;
|
||||
}
|
||||
|
||||
// TODO: Do we need to debounce encoder?
|
||||
// debounce
|
||||
auto now = millis();
|
||||
if (now - lastEncoderChangeAt < DEBOUNCE_MS) {
|
||||
return SWITCH_NONE;
|
||||
}
|
||||
|
||||
// clockwise pattern:
|
||||
// clk: 1001 1001
|
||||
|
@ -78,6 +82,7 @@ EncoderEvent handleEncoder() {
|
|||
// save state
|
||||
previousClk = clk;
|
||||
previousDt = dt;
|
||||
lastEncoderChangeAt = now;
|
||||
|
||||
// return event
|
||||
return event;
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#include "constants.h"
|
||||
#include "debug.h"
|
||||
#include "buzzer.h"
|
||||
#include "keyboard.h"
|
||||
|
||||
PCF8574 kbd(KBD_I2C_ADDR, &Wire);
|
||||
|
||||
|
@ -15,15 +17,10 @@ row/col 0 1 2 3
|
|||
1 4 5 6 B
|
||||
2 7 8 9 C
|
||||
3 * 0 # D
|
||||
|
||||
Keys, in order:
|
||||
123A 456B 789C *0#D
|
||||
*/
|
||||
|
||||
typedef uint8_t Key;
|
||||
|
||||
const char *allKeys = "123A456B789C*0#D";
|
||||
#define KEY_NONE 255
|
||||
|
||||
const uint8_t digits[16] =
|
||||
{ 1, 2, 3, KEY_NONE,
|
||||
4, 5, 6, KEY_NONE,
|
||||
|
@ -43,30 +40,35 @@ bool setupKeyboard() {
|
|||
return true;
|
||||
}
|
||||
|
||||
Key previousKey = KEY_NONE;
|
||||
unsigned long lastPressedAt = 0;
|
||||
|
||||
Key getPressedKey();
|
||||
uint8_t getPressedDigit(Key key);
|
||||
Key handleKeyboard() {
|
||||
auto key = getPressedKey();
|
||||
|
||||
// only handle change
|
||||
if (key == previousKey) {
|
||||
return KEY_NONE;
|
||||
}
|
||||
|
||||
// debounce
|
||||
auto now = millis();
|
||||
if (now - lastPressedAt < DEBOUNCE_MS) {
|
||||
return KEY_NONE;
|
||||
}
|
||||
|
||||
// save state
|
||||
previousKey = key;
|
||||
lastPressedAt = now;
|
||||
|
||||
// return event
|
||||
return key;
|
||||
}
|
||||
|
||||
#define KBD_COL_MASK 0b11110000
|
||||
#define KBD_ROW_MASK 0b00001111
|
||||
|
||||
void demoKeyboard() {
|
||||
auto key = getPressedKey();
|
||||
if (key != KEY_NONE) {
|
||||
Serial.print("Key pressed: ");
|
||||
Serial.print(allKeys[key]);
|
||||
|
||||
auto digit = getPressedDigit(key);
|
||||
if (digit != KEY_NONE) {
|
||||
Serial.print(", digit: ");
|
||||
Serial.print(digit);
|
||||
} else {
|
||||
Serial.print(" (Not a digit)");
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pressed key or KEY_NONE if no key is pressed
|
||||
*
|
||||
|
@ -89,27 +91,40 @@ Key getPressedKey() {
|
|||
else if (colState & 0b0100) colPressed = 1;
|
||||
else if (colState & 0b0010) colPressed = 2;
|
||||
else if (colState & 0b0001) colPressed = 3;
|
||||
else fatal();
|
||||
else {
|
||||
Serial.print("Invalid kbd column state: ");
|
||||
Serial.println(cols, BIN);
|
||||
sadBuzz();
|
||||
return KEY_NONE;
|
||||
}
|
||||
|
||||
// check pressed row
|
||||
// last 4 bits are rows, low when pressed
|
||||
kbd.write8(KBD_ROW_MASK);
|
||||
|
||||
uint8_t rowState = ~kbd.read8();
|
||||
uint8_t rows = kbd.read8();
|
||||
if (rows == KBD_ROW_MASK) {
|
||||
// between col and row read, a key could be released
|
||||
return KEY_NONE;
|
||||
}
|
||||
|
||||
uint8_t rowState = ~rows;
|
||||
uint8_t rowPressed = 0;
|
||||
if (rowState & 0b1000) rowPressed = 0;
|
||||
else if (rowState & 0b0100) rowPressed = 1;
|
||||
else if (rowState & 0b0010) rowPressed = 2;
|
||||
else if (rowState & 0b0001) rowPressed = 3;
|
||||
else fatal();
|
||||
else {
|
||||
Serial.print("Invalid kbd row state: ");
|
||||
Serial.println(rowState, BIN);
|
||||
sadBuzz();
|
||||
return KEY_NONE;
|
||||
}
|
||||
|
||||
// return key
|
||||
return (rowPressed * 4) + colPressed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns pressed digit or KEY_NONE if the key is not a digit
|
||||
*/
|
||||
uint8_t getPressedDigit(Key key) {
|
||||
if (key == KEY_NONE) return KEY_NONE;
|
||||
return digits[key];
|
||||
|
|
|
@ -1,4 +1,32 @@
|
|||
#pragma once
|
||||
|
||||
/*
|
||||
Keys, in order:
|
||||
123A 456B 789C *0#D
|
||||
*/
|
||||
typedef uint8_t Key;
|
||||
#define KEY_NONE 255
|
||||
#define KEY_A 3
|
||||
#define KEY_B 7
|
||||
#define KEY_C 11
|
||||
#define KEY_D 15
|
||||
#define KEY_ASTERISK 12
|
||||
#define KEY_HASH 14
|
||||
|
||||
extern const char *allKeys;
|
||||
|
||||
bool setupKeyboard();
|
||||
void demoKeyboard();
|
||||
|
||||
/**
|
||||
* Returns pressed key once upon its release
|
||||
* or KEY_NONE if no key is pressed
|
||||
*
|
||||
* NOTE: Only one key can be pressed at a time;
|
||||
* if multiple keys are pressed, the behavior is undefined
|
||||
*/
|
||||
Key handleKeyboard();
|
||||
|
||||
/**
|
||||
* Returns pressed digit or KEY_NONE if the key is not a digit
|
||||
*/
|
||||
uint8_t getPressedDigit(Key key);
|
||||
|
|
|
@ -7,10 +7,14 @@
|
|||
#include "keyboard.h"
|
||||
#include "encoder.h"
|
||||
#include "debug.h"
|
||||
#include "timer.h"
|
||||
#include "stepper.h"
|
||||
|
||||
void setup() {
|
||||
setupDebug();
|
||||
setupEncoder();
|
||||
setupTimer();
|
||||
setupStepper();
|
||||
|
||||
Wire.begin();
|
||||
|
||||
|
@ -22,11 +26,39 @@ void setup() {
|
|||
}
|
||||
|
||||
void loop() {
|
||||
// tick();
|
||||
|
||||
// debugScanI2C();
|
||||
// demoScreen();
|
||||
// demoKeyboard();
|
||||
// demoStepper();
|
||||
|
||||
demoTimer();
|
||||
|
||||
auto key = handleKeyboard();
|
||||
if (key != KEY_NONE) {
|
||||
Serial.print("Key pressed: ");
|
||||
Serial.print(allKeys[key]);
|
||||
|
||||
auto digit = getPressedDigit(key);
|
||||
if (digit != KEY_NONE) {
|
||||
Serial.print(", digit: ");
|
||||
Serial.print(digit);
|
||||
} else {
|
||||
Serial.print(" (Not a digit)");
|
||||
}
|
||||
|
||||
Serial.println();
|
||||
|
||||
if (key == KEY_A) {
|
||||
happyBuzz();
|
||||
} else if (key == KEY_B) {
|
||||
sadBuzz();
|
||||
} else if (key == KEY_C) {
|
||||
beep();
|
||||
} else if (key == KEY_D) {
|
||||
tick();
|
||||
} else {
|
||||
tick();
|
||||
}
|
||||
}
|
||||
|
||||
if (auto event = handleSwitch()) {
|
||||
tick();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#include <Arduino.h>
|
||||
#include "constants.h"
|
||||
|
||||
void setupStepper() {
|
||||
pinMode(STEPPER_ENABLE, OUTPUT);
|
||||
pinMode(STEPPER_DIR, OUTPUT);
|
||||
pinMode(STEPPER_STEP, OUTPUT);
|
||||
|
||||
// low = enabled
|
||||
digitalWrite(STEPPER_ENABLE, LOW);
|
||||
}
|
||||
|
||||
bool stepperDir = HIGH;
|
||||
|
||||
void demoStepper() {
|
||||
Serial.println("Demoing stepper motor - rotating 200 steps");
|
||||
stepperDir = !stepperDir;
|
||||
digitalWrite(STEPPER_DIR, stepperDir);
|
||||
for (int i = 0; i < 200; i++) {
|
||||
digitalWrite(STEPPER_STEP, HIGH);
|
||||
delay(2);
|
||||
digitalWrite(STEPPER_STEP, LOW);
|
||||
delay(7);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#pragma once
|
||||
|
||||
void setupStepper();
|
||||
void demoStepper();
|
|
@ -0,0 +1,46 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
#define DEMO_TRIGGER_MS 1500
|
||||
|
||||
void setupTimer() {
|
||||
// Set up Timer 0 to trigger interrupt every 1ms
|
||||
// Timer 0 is already used and configured by Arduino for millis()
|
||||
// however it uses TOIE0 (overflow interrupt), so we'll use OCIE0A:
|
||||
// When this bit is written to one, and the I-flag in the Status Register is set
|
||||
// (interrupts globally enabled), the Timer/Counter0 Output Compare A Match interrupt is enabled
|
||||
// The corresponding Interrupt Vector is executed when the OCF0A Flag, located in TIFR0, is set.
|
||||
OCR0A = 0xAF; // any number is OK, it will trigger at some point during the counter
|
||||
TIMSK0 |= _BV(OCIE0A);
|
||||
}
|
||||
|
||||
// incremented every DEMO_TRIGGER_MS by interrupt,
|
||||
// read and decremented by main loop
|
||||
volatile uint8_t timerEvents = 0;
|
||||
|
||||
void demoTimer() {
|
||||
bool shouldTrigger = false;
|
||||
|
||||
noInterrupts();
|
||||
if (timerEvents > 0) {
|
||||
timerEvents--;
|
||||
shouldTrigger = true;
|
||||
}
|
||||
interrupts();
|
||||
|
||||
if (shouldTrigger) {
|
||||
Serial.println("Timer tick!");
|
||||
}
|
||||
}
|
||||
|
||||
volatile uint16_t timerMillis = 0;
|
||||
|
||||
// triggers every 1ms
|
||||
ISR(TIMER0_COMPA_vect) {
|
||||
timerMillis++;
|
||||
if (timerMillis >= DEMO_TRIGGER_MS) {
|
||||
timerMillis -= DEMO_TRIGGER_MS;
|
||||
timerEvents++;
|
||||
}
|
||||
|
||||
// TODO: Add motor encoder reading, calculate required carriage offset, control stepper
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
void setupTimer();
|
||||
void demoTimer();
|
Loading…
Reference in New Issue