mirror of
https://github.com/vladkorotnev/wacca-vfd-arduino.git
synced 2024-11-12 01:00:50 +01:00
Make it count coins
This commit is contained in:
parent
574a019cbb
commit
27b31c5ae6
6
firm/.vscode/c_cpp_properties.json
vendored
6
firm/.vscode/c_cpp_properties.json
vendored
@ -10,9 +10,10 @@
|
||||
"includePath": [
|
||||
"d:/Code/wacca-vfd/firm/include",
|
||||
"d:/Code/wacca-vfd/firm/src",
|
||||
"d:/Code/wacca-vfd/firm/.pio/libdeps/sparkfun_promicro8/EEPROMWearLevel/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/cores/arduino",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/variants/sparkfun_promicro",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/HID/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/SPI/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/SoftwareSerial/src",
|
||||
@ -24,9 +25,10 @@
|
||||
"path": [
|
||||
"d:/Code/wacca-vfd/firm/include",
|
||||
"d:/Code/wacca-vfd/firm/src",
|
||||
"d:/Code/wacca-vfd/firm/.pio/libdeps/sparkfun_promicro8/EEPROMWearLevel/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/cores/arduino",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/variants/sparkfun_promicro",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/EEPROM/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/HID/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/SPI/src",
|
||||
"C:/Users/akasaka/.platformio/packages/framework-arduino-avr/libraries/SoftwareSerial/src",
|
||||
|
12
firm/include/coin.h
Normal file
12
firm/include/coin.h
Normal file
@ -0,0 +1,12 @@
|
||||
#ifndef COIN_H_
|
||||
#define COIN_H_
|
||||
#include <stdint.h>
|
||||
|
||||
void coin_begin();
|
||||
void coin_set_callback(void (*fun_ptr)(uint32_t, uint32_t));
|
||||
void coin_save_if_needed();
|
||||
uint32_t coin_get();
|
||||
uint32_t coin_get_amt();
|
||||
bool coin_reset_if_needed();
|
||||
|
||||
#endif
|
17
firm/include/settings.h
Normal file
17
firm/include/settings.h
Normal file
@ -0,0 +1,17 @@
|
||||
#ifndef SETTINGS_H_
|
||||
#define SETTINGS_H_
|
||||
#include <stdint.h>
|
||||
|
||||
void cfg_begin();
|
||||
|
||||
typedef enum cfg_index {
|
||||
CFG_READY = 0,
|
||||
COIN_COUNT = 1,
|
||||
MAX_INVALID
|
||||
} cfg_index_t;
|
||||
|
||||
bool cfg_valid();
|
||||
int32_t cfg_read(cfg_index_t);
|
||||
void cfg_write(cfg_index_t, int32_t value);
|
||||
|
||||
#endif
|
@ -11,7 +11,9 @@
|
||||
[env:sparkfun_promicro8]
|
||||
platform = atmelavr
|
||||
board = sparkfun_promicro8
|
||||
upload_port = COM25
|
||||
monitor_port = COM25
|
||||
upload_port = COM18
|
||||
monitor_port = COM18
|
||||
monitor_speed = 9600
|
||||
framework = arduino
|
||||
lib_deps =
|
||||
prosenb/EEPROMWearLevel@^2.1.0
|
||||
|
76
firm/src/coin.cpp
Normal file
76
firm/src/coin.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
#include <coin.h>
|
||||
#include <settings.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#define COIN_PIN 2
|
||||
#define COIN_DENOMINATION 100
|
||||
|
||||
static volatile int32_t coin_count_cache = 0;
|
||||
static volatile bool coin_need_save = false;
|
||||
static void (*callback)(uint32_t, uint32_t) = nullptr;
|
||||
|
||||
void coin_call_callback() {
|
||||
if(callback != nullptr && coin_count_cache > 0) {
|
||||
callback(coin_count_cache, coin_count_cache * COIN_DENOMINATION);
|
||||
}
|
||||
}
|
||||
|
||||
void coin_ISR() {
|
||||
static unsigned long debounce_timer = 0;
|
||||
unsigned long now_timer = millis();
|
||||
if(now_timer - debounce_timer > 200) {
|
||||
coin_count_cache++;
|
||||
coin_need_save = true;
|
||||
coin_call_callback();
|
||||
debounce_timer = now_timer;
|
||||
}
|
||||
}
|
||||
|
||||
void coin_begin() {
|
||||
callback = nullptr;
|
||||
pinMode(COIN_PIN, INPUT_PULLUP);
|
||||
if(cfg_valid()) {
|
||||
coin_count_cache = cfg_read(cfg_index::COIN_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
bool coin_reset_if_needed() {
|
||||
bool rslt = false;
|
||||
if(digitalRead(COIN_PIN) == LOW) {
|
||||
int millis_start = millis();
|
||||
while(digitalRead(COIN_PIN) == LOW) delay(1);
|
||||
if(millis() - millis_start > 2000) {
|
||||
cfg_write(cfg_index::COIN_COUNT, 0);
|
||||
rslt = true;
|
||||
}
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
|
||||
bool haveInterrupt = false;
|
||||
void coin_set_callback(void (*fun_ptr)(uint32_t, uint32_t)) {
|
||||
if(!haveInterrupt) {
|
||||
attachInterrupt(digitalPinToInterrupt(COIN_PIN), coin_ISR, LOW);
|
||||
haveInterrupt = true;
|
||||
}
|
||||
callback = fun_ptr;
|
||||
}
|
||||
|
||||
|
||||
void coin_save_if_needed() {
|
||||
if(coin_need_save) {
|
||||
cli();
|
||||
cfg_write(cfg_index_t::COIN_COUNT, coin_count_cache);
|
||||
coin_need_save = false;
|
||||
sei();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t coin_get() {
|
||||
return coin_count_cache;
|
||||
}
|
||||
|
||||
uint32_t coin_get_amt() {
|
||||
return coin_get() * COIN_DENOMINATION;
|
||||
}
|
@ -1,82 +1,184 @@
|
||||
#include <Arduino.h>
|
||||
#include <futaba.h>
|
||||
#include <rsrc.h>
|
||||
#include <settings.h>
|
||||
#include <coin.h>
|
||||
|
||||
extern "C" {
|
||||
void setup();
|
||||
void loop();
|
||||
}
|
||||
|
||||
volatile uint16_t time_coin_remain = 0;
|
||||
volatile uint32_t coin_amount = 0;
|
||||
uint32_t coin_disp_amount = 0;
|
||||
volatile uint16_t coin_combo = 0;
|
||||
|
||||
void coin_callback(uint32_t count, uint32_t amount) {
|
||||
time_coin_remain = 5000;
|
||||
coin_combo++;
|
||||
coin_amount = amount;
|
||||
}
|
||||
|
||||
bool task_coin() {
|
||||
if(time_coin_remain == 0) return false;
|
||||
|
||||
time_coin_remain--;
|
||||
|
||||
if(coin_disp_amount != coin_amount) {
|
||||
ftb_canvas_shift(0);
|
||||
char buf[21] = { 0 };
|
||||
ftb_cursor(0, 0);
|
||||
if(coin_combo < 2) {
|
||||
ftb_write("** SAVE SOME CASH **");
|
||||
} else {
|
||||
ftb_write("** ");
|
||||
sprintf(buf, "%u COMBO", coin_combo);
|
||||
ftb_write(buf);
|
||||
ftb_write(" **");
|
||||
memset(buf, 0, 21);
|
||||
}
|
||||
ftb_cursor(0, 2);
|
||||
sprintf(buf, "TOTAL: %lu \\", coin_amount);
|
||||
ftb_write(buf);
|
||||
coin_disp_amount = coin_amount;
|
||||
}
|
||||
|
||||
if(time_coin_remain == 0) {
|
||||
coin_combo = 0;
|
||||
ftb_cursor(0, 0);
|
||||
ftb_write(" ");
|
||||
ftb_cursor(0, 2);
|
||||
ftb_write(" ");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void setup() {
|
||||
cfg_begin();
|
||||
coin_begin();
|
||||
ftb_init();
|
||||
|
||||
delay(1000);
|
||||
|
||||
ftb_reset();
|
||||
ftb_power(true);
|
||||
ftb_brightness(BRIGHT_25);
|
||||
ftb_brightness(BRIGHT_50);
|
||||
|
||||
ftb_canvas_shift(0);
|
||||
ftb_cursor(0, 0);
|
||||
ftb_font_size(FONT_16_16);
|
||||
|
||||
bool coin_did_reset = coin_reset_if_needed();
|
||||
if(coin_did_reset) {
|
||||
ftb_cursor(0, 0);
|
||||
ftb_write("** COIN COUNT CLR **");
|
||||
delay(2000);
|
||||
ftb_cursor(0, 0);
|
||||
ftb_write(" ");
|
||||
}
|
||||
|
||||
coin_set_callback(coin_callback);
|
||||
}
|
||||
|
||||
void scroll_from_to(uint16_t from, uint16_t to, uint16_t w) {
|
||||
for(uint16_t x = from; x < to; x++) {
|
||||
ftb_canvas_shift(x);
|
||||
delay(w);
|
||||
typedef enum {
|
||||
LOGO_IN,
|
||||
LOGO_STAY,
|
||||
LOGO_OUT,
|
||||
TANOC_IN,
|
||||
TANOC_STAY,
|
||||
TANOC_OUT,
|
||||
AMT_IN,
|
||||
AMT_STAY,
|
||||
AMT_OUT,
|
||||
} idle_phase;
|
||||
|
||||
idle_phase now_phase = LOGO_IN;
|
||||
uint32_t logo_left = 0;
|
||||
uint32_t logo_time = 0;
|
||||
|
||||
void task_idle() {
|
||||
switch(now_phase) {
|
||||
case LOGO_IN:
|
||||
case TANOC_IN:
|
||||
if(logo_left == 0) {
|
||||
ftb_cursor(0, 0);
|
||||
ftb_draw_image(now_phase == LOGO_IN ? &IMG_WOCAO : &IMG_TANOC, 160, 0);
|
||||
} else {
|
||||
ftb_canvas_shift(logo_left);
|
||||
}
|
||||
logo_left++;
|
||||
if(logo_left == 161) {
|
||||
now_phase = (now_phase == LOGO_IN ? LOGO_STAY : TANOC_STAY);
|
||||
logo_time = 1000;
|
||||
}
|
||||
break;
|
||||
|
||||
case AMT_IN:
|
||||
if(logo_left == 0) {
|
||||
char buf1[21] = {0};
|
||||
char buf2[21] = {0};
|
||||
sprintf(buf1, "%lu coins", coin_get());
|
||||
sprintf(buf2, "Total: %lu \\", coin_get_amt());
|
||||
ftb_cursor(160, 0);
|
||||
ftb_write(" ");
|
||||
ftb_cursor(160, 0);
|
||||
ftb_write(buf1);
|
||||
ftb_cursor(160, 2);
|
||||
ftb_write(" ");
|
||||
ftb_cursor(160, 2);
|
||||
ftb_write(buf2);
|
||||
} else {
|
||||
ftb_canvas_shift(logo_left);
|
||||
}
|
||||
logo_left++;
|
||||
if(logo_left == 161) {
|
||||
now_phase = AMT_STAY;
|
||||
logo_time = 1000;
|
||||
}
|
||||
break;
|
||||
|
||||
case LOGO_STAY:
|
||||
case TANOC_STAY:
|
||||
case AMT_STAY:
|
||||
logo_time--;
|
||||
if(logo_time == 0) {
|
||||
switch(now_phase) {
|
||||
case LOGO_STAY: now_phase = LOGO_OUT; break;
|
||||
case TANOC_STAY: now_phase = TANOC_OUT; break;
|
||||
case AMT_STAY: now_phase = AMT_OUT; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case LOGO_OUT:
|
||||
case TANOC_OUT:
|
||||
case AMT_OUT:
|
||||
ftb_canvas_shift(logo_left);
|
||||
logo_left++;
|
||||
if(logo_left == 160*2 + 1) {
|
||||
switch(now_phase) {
|
||||
case LOGO_OUT: now_phase = TANOC_IN; break;
|
||||
case TANOC_OUT: now_phase = AMT_IN; break;
|
||||
case AMT_OUT: now_phase = LOGO_IN; break;
|
||||
}
|
||||
logo_left = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long last_millis = 0;
|
||||
void loop() {
|
||||
img_data_t tmp;
|
||||
ftb_canvas_shift(0);
|
||||
tmp = img_invert(&IMG_WOCAO);
|
||||
ftb_draw_image(&IMG_WOCAO, 160, 0);
|
||||
scroll_from_to(0, 160, 10);
|
||||
delay(1000);
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ftb_cursor(0, 0);
|
||||
ftb_draw_image(&tmp, 160, 0);
|
||||
delay(250);
|
||||
ftb_cursor(0, 0);
|
||||
ftb_draw_image(&IMG_WOCAO, 160, 0);
|
||||
delay(250);
|
||||
unsigned long now_time = millis();
|
||||
if(now_time - last_millis > 1) {
|
||||
last_millis = now_time;
|
||||
if(task_coin()) {
|
||||
now_phase = LOGO_IN;
|
||||
logo_left = 0;
|
||||
coin_save_if_needed();
|
||||
return;
|
||||
}
|
||||
|
||||
task_idle();
|
||||
}
|
||||
scroll_from_to(160, 160 * 2, 10);
|
||||
|
||||
ftb_cursor(160 * 3, 0);
|
||||
ftb_write(" ");
|
||||
|
||||
ftb_canvas_shift(0);
|
||||
tmp = img_invert(&IMG_TANOC);
|
||||
ftb_cursor(0, 0);
|
||||
|
||||
ftb_draw_image(&IMG_TANOC, 160, 0);
|
||||
scroll_from_to(0, 160, 10);
|
||||
delay(1000);
|
||||
for(int i = 0; i < 4; i++) {
|
||||
ftb_cursor(0, 0);
|
||||
ftb_draw_image(&tmp, 160, 0);
|
||||
delay(250);
|
||||
ftb_cursor(0, 0);
|
||||
ftb_draw_image(&IMG_TANOC, 160, 0);
|
||||
delay(250);
|
||||
}
|
||||
scroll_from_to(160, 160 * 2, 10);
|
||||
|
||||
ftb_cursor(160 * 3, 0);
|
||||
ftb_write("** ALL SAS OELUTZ **");
|
||||
|
||||
scroll_from_to(160*2, 160 * 3, 10);
|
||||
|
||||
ftb_scroll_box_make(0, 2, 160, 2);
|
||||
ftb_scroll_speed(2);
|
||||
ftb_scroll_text("Are you ready to RAVE to the music of HARDCORE TANO-C?? ENJOY the SUPER COOL mega Game WACCA, sunovabitch!! ");
|
||||
ftb_scroll_start();
|
||||
|
||||
delay(10000);
|
||||
|
||||
ftb_scroll_text("");
|
||||
}
|
||||
|
28
firm/src/settings.cpp
Normal file
28
firm/src/settings.cpp
Normal file
@ -0,0 +1,28 @@
|
||||
#include <settings.h>
|
||||
#include <Arduino.h>
|
||||
#include <EEPROMWearLevel.h>
|
||||
|
||||
#define SETTINGS_VERSION 0
|
||||
#define SETTINGS_MAGIC 0x3939
|
||||
|
||||
void cfg_begin() {
|
||||
EEPROMwl.begin(SETTINGS_VERSION, cfg_index::MAX_INVALID);
|
||||
if(!cfg_valid()) {
|
||||
cfg_write(cfg_index::COIN_COUNT, 0);
|
||||
cfg_write(cfg_index::CFG_READY, SETTINGS_MAGIC);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t cfg_read(cfg_index_t idx) {
|
||||
int32_t tmp = -1;
|
||||
EEPROMwl.get(idx, tmp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void cfg_write(cfg_index_t idx, int32_t value) {
|
||||
EEPROMwl.put(idx, value);
|
||||
}
|
||||
|
||||
bool cfg_valid() {
|
||||
return cfg_read(cfg_index::CFG_READY) == SETTINGS_MAGIC;
|
||||
}
|
Loading…
Reference in New Issue
Block a user