#include <MsTimer2.h>
#include <Adafruit_SSD1306.h>
#define TACT_SWITCH_PIN 2 // スイッチ
#define VOLUME_PIN A0 // 可変抵抗
#define SHIFT_RESISTOR_PIN_DS 3 // シリアルデータ
#define SHIFT_RESISTOR_PIN_SHCP 4 // シリアルクロック
#define SHIFT_RESISTOR_PIN_STCP 5 // ラッチ
#define SHIFT_RESISTOR_PIN_OE 6 // 出力イネーブル
#define SEGMENT_DIGIT_PIN_1 8 // 桁選択 1
#define SEGMENT_DIGIT_PIN_2 9 // 桁選択 2
#define SEGMENT_DIGIT_PIN_3 10 // 桁選択 3
#define SEGMENT_DIGIT_PIN_4 11 // 桁選択 4
#define LCD_ADDRESS 0x3C
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin)
void numToTime(uint32_t num, uint8_t index, uint8_t time[]);
uint8_t SegCnt[] = {
0xC0, 0xF9, 0xA4, 0xB0, 0x99,
0x92, 0x82, 0xD8, 0x80, 0x90
};
uint8_t SegPin[] = {
SHIFT_RESISTOR_PIN_DS, SHIFT_RESISTOR_PIN_SHCP, SHIFT_RESISTOR_PIN_STCP, SHIFT_RESISTOR_PIN_OE,
SEGMENT_DIGIT_PIN_1, SEGMENT_DIGIT_PIN_2, SEGMENT_DIGIT_PIN_3, SEGMENT_DIGIT_PIN_4
};
uint8_t digitPin[] = {
SEGMENT_DIGIT_PIN_1, SEGMENT_DIGIT_PIN_2, SEGMENT_DIGIT_PIN_3, SEGMENT_DIGIT_PIN_4
};
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
volatile uint32_t timeCnt = 0;
volatile boolean swFlg = HIGH;
void count() {
timeCnt++;
}
void callbackTactSw() {
swFlg = digitalRead(TACT_SWITCH_PIN);
}
void setup() {
// 入力ピン
pinMode(TACT_SWITCH_PIN, INPUT);
pinMode(VOLUME_PIN, INPUT);
// 出力ピン
for (uint8_t i = 0; i < sizeof(SegPin); i++) {
digitalWrite(SegPin[i], LOW);
pinMode(SegPin[i], OUTPUT);
}
// LCD (SSD1306)
display.begin(SSD1306_SWITCHCAPVCC, LCD_ADDRESS);
display.setTextColor(SSD1306_WHITE);
display.setTextSize(1);
// 外部割込み
attachInterrupt(digitalPinToInterrupt(TACT_SWITCH_PIN), callbackTactSw, CHANGE);
// タイマー割り込み
MsTimer2::set(1000, count); // 1000msごと
MsTimer2::start();
}
void loop() {
uint8_t time[4];
// 可変抵抗値取得
uint16_t regVal = map(analogRead(VOLUME_PIN), 0, 1023, ((swFlg == LOW)? 500 : 1000), 1);
// LCD に表示
display.clearDisplay();
display.setCursor(0, 0);
display.println("Period per digit");
display.print(regVal);
//display.println(" ms");
display.println(" ms\n\nBlank time\n100 us");
display.display();
// ダイナミック点灯
for (uint8_t i = 0; i < sizeof(digitPin); i++) {
numToTime(timeCnt, i, time);
digitalWrite(SHIFT_RESISTOR_PIN_STCP, LOW);
shiftOut(SHIFT_RESISTOR_PIN_DS, SHIFT_RESISTOR_PIN_SHCP, MSBFIRST,
(SegCnt[time[i]] & ((i == 1)? 0x7F : 0xFF)));
digitalWrite(SHIFT_RESISTOR_PIN_STCP, HIGH);
digitalWrite(digitPin[i], HIGH);
delay(regVal); // 各桁の周期時間
digitalWrite(digitPin[i], LOW);
delayMicroseconds(100); // ブランク時間
}
}
void numToTime(uint32_t num, uint8_t index, uint8_t time[]) {
static const uint16_t freq[] = {600, 60, 10, 1};
static const uint8_t surplus[] = {6, 10, 6, 10};
time[index] = (num / freq[index]) % surplus[index];
}