add clap button
This commit is contained in:
parent
f3e93d4c67
commit
b6320b0ddf
298
main.c
298
main.c
|
@ -53,6 +53,7 @@
|
|||
volatile bool rtc_tick_flag = false; /**< flag set when RTC ticked */
|
||||
volatile bool frame_flag = false; /**< flag set when a frame has passed */
|
||||
volatile bool keep_alive_flag = false; /**< flag to restart shutdown counter on power switch activity */
|
||||
volatile bool clap_flag = false; /**< flag set on clap */
|
||||
/** @} */
|
||||
|
||||
#define SQUARE_WAVE_PORT B /**< port connected to RTC DS1307 square wave output */
|
||||
|
@ -114,6 +115,15 @@ struct number_t numbers[] = {
|
|||
#define BUTTONS_READ_PIN2 6
|
||||
#define BUTTONS_READ_PIN3 15
|
||||
|
||||
#define CLAP_BUTTON_PORT B
|
||||
#define CLAP_BUTTON_PIN 14
|
||||
|
||||
/** Morse code variables, to buzz scene and take */
|
||||
#define MORSE_DOT 1 /**< unit Morse code duration in frames */
|
||||
uint8_t morse[2*4*5*2] = {0}; /**< to encode 2 4-digit numbers (scene and take) into Morse code (5 sign+space) */
|
||||
uint8_t morse_i = 0; /**< index in Morse array */
|
||||
int16_t morse_delay = -1; /**< number of frames before beeping (-1=no need to beep yet, -2=beeping completed) */
|
||||
|
||||
/** user input command */
|
||||
static char command[32] = {0};
|
||||
/** user input command index */
|
||||
|
@ -278,115 +288,122 @@ static void mux_select(uint8_t output)
|
|||
}
|
||||
}
|
||||
|
||||
/** unit Morse code duration in frames */
|
||||
#define MORSE_DOT 10
|
||||
uint8_t morse[1*4*5*2] = {0};
|
||||
uint8_t morse_i = 0;
|
||||
|
||||
static void encode_morse(void)
|
||||
{
|
||||
bool not_zero = false;
|
||||
for (uint8_t digit=0; digit<4; digit++) {
|
||||
uint16_t number = 42;
|
||||
// get only the digit from the number
|
||||
for (uint8_t divide=digit; divide<3; divide++) {
|
||||
number /= 10;
|
||||
}
|
||||
number %= 10;
|
||||
// remember when we found the first non-zero digit
|
||||
if (number!=0 || digit==3) {
|
||||
not_zero = true;
|
||||
}
|
||||
// encode the number in Morse code (1=short, 3=long)
|
||||
switch (number) {
|
||||
case 1:
|
||||
morse[digit*2*5+0] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 2:
|
||||
morse[digit*2*5+0] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 3:
|
||||
morse[digit*2*5+0] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 4:
|
||||
morse[digit*2*5+0] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 5:
|
||||
morse[digit*2*5+0] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 6:
|
||||
morse[digit*2*5+0] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 7:
|
||||
morse[digit*2*5+0] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 8:
|
||||
morse[digit*2*5+0] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 1*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 9:
|
||||
morse[digit*2*5+0] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 0:
|
||||
if (not_zero) {
|
||||
morse[digit*2*5+0] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+2] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+4] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+6] = 3*MORSE_DOT;
|
||||
morse[digit*2*5+8] = 3*MORSE_DOT;
|
||||
} else { //don't encode the first digits if they are zero
|
||||
morse[digit*2*5+0] = 0;
|
||||
morse[digit*2*5+2] = 0;
|
||||
morse[digit*2*5+4] = 0;
|
||||
morse[digit*2*5+6] = 0;
|
||||
morse[digit*2*5+8] = 0;
|
||||
// encode numbers (scene and take) in Morse code
|
||||
uint16_t morse_numbers[] = {numbers[0].number, numbers[1].number};
|
||||
printf("scene: %u, take: %u\n", morse_numbers[0], morse_numbers[1]);
|
||||
for (uint8_t morse_number=0; morse_number<LENGTH(morse_numbers); morse_number++) {
|
||||
bool not_zero = false; // has the first non-zero digit been found
|
||||
if (0xffff==morse_numbers[morse_number]) { // number disabled, don't beep
|
||||
for (uint8_t i=morse_number*4*2*5; i<(morse_number+1)*4*2*5; i++) {
|
||||
morse[i] = 0;
|
||||
}
|
||||
} else { // encode number in Morse code
|
||||
for (uint8_t digit=0; digit<4; digit++) {
|
||||
uint16_t number = morse_numbers[morse_number];
|
||||
// get only the digit from the number
|
||||
for (uint8_t divide=digit; divide<3; divide++) {
|
||||
number /= 10;
|
||||
}
|
||||
number %= 10;
|
||||
// remember when we found the first non-zero digit
|
||||
if (number!=0 || digit==3) {
|
||||
not_zero = true;
|
||||
}
|
||||
// encode digit in Morse code (1=short, 3=long)
|
||||
switch (number) {
|
||||
case 1:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 2:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 3:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 4:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 3*MORSE_DOT;
|
||||
break;
|
||||
case 5:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 6:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 7:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 8:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 1*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 9:
|
||||
morse[(morse_number*4+digit)*2*5+0] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 1*MORSE_DOT;
|
||||
break;
|
||||
case 0:
|
||||
if (not_zero) {
|
||||
morse[(morse_number*4+digit)*2*5+0] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 3*MORSE_DOT;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 3*MORSE_DOT;
|
||||
} else { //don't encode the first digits if they are zero
|
||||
morse[(morse_number*4+digit)*2*5+0] = 0;
|
||||
morse[(morse_number*4+digit)*2*5+2] = 0;
|
||||
morse[(morse_number*4+digit)*2*5+4] = 0;
|
||||
morse[(morse_number*4+digit)*2*5+6] = 0;
|
||||
morse[(morse_number*4+digit)*2*5+8] = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// fill the spaces between the dots
|
||||
for (uint8_t space=0; space<5; space++) {
|
||||
if (0==morse[(morse_number*4+digit)*2*5+space*2]) {
|
||||
morse[(morse_number*4+digit)*2*5+space*2+1] = 0;
|
||||
} else {
|
||||
morse[(morse_number*4+digit)*2*5+space*2+1] = 1*MORSE_DOT;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// fill the spaces between the dots
|
||||
for (uint8_t space=0; space<5; space++) {
|
||||
if (0==morse[digit*2*5+space*2]) {
|
||||
morse[digit*2*5+space*2+1] = 0;
|
||||
} else {
|
||||
morse[digit*2*5+space*2+1] = 1*MORSE_DOT;
|
||||
}
|
||||
}
|
||||
}
|
||||
morse[4*2*5+1] = 3*MORSE_DOT; // add silence between the two numbers
|
||||
morse_i = 0; // reset Morse index
|
||||
}
|
||||
|
||||
|
@ -571,7 +588,7 @@ void main(void)
|
|||
printf("OK\n");
|
||||
|
||||
// setup GPIO for reading buttons
|
||||
printf("setup button inputs: ");
|
||||
printf("setup display buttons: ");
|
||||
rcc_periph_clock_enable(RCC_GPIO(BUTTONS_DRIVE_PORT)); // enable clock for GPIO port domain
|
||||
// no need to configure the driving line modes since this will be done when they need to be driven
|
||||
rcc_periph_clock_enable(RCC_GPIO(BUTTONS_READ_PORT)); // enable clock for GPIO port domain
|
||||
|
@ -581,8 +598,16 @@ void main(void)
|
|||
uint16_t buttons = 0;
|
||||
printf("OK\n");
|
||||
|
||||
encode_morse();
|
||||
bool announce = false;
|
||||
printf("setup clap button: ");
|
||||
rcc_periph_clock_enable(RCC_GPIO(CLAP_BUTTON_PORT)); // enable clock for GPIO port domain
|
||||
gpio_set_mode(GPIO(CLAP_BUTTON_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO(CLAP_BUTTON_PIN)); // set button pin to input
|
||||
gpio_set(GPIO(CLAP_BUTTON_PORT), GPIO(CLAP_BUTTON_PIN)); // pull up
|
||||
rcc_periph_clock_enable(RCC_AFIO); // enable alternate function clock for external interrupt
|
||||
exti_select_source(EXTI(CLAP_BUTTON_PIN), GPIO(CLAP_BUTTON_PORT)); // mask external interrupt of this pin only for this port
|
||||
exti_set_trigger(EXTI(CLAP_BUTTON_PIN), EXTI_TRIGGER_FALLING); // trigger on falling edge (we are pulling up on one side, and ground is on the other side)
|
||||
exti_enable_request(EXTI(CLAP_BUTTON_PIN)); // enable external interrupt
|
||||
nvic_enable_irq(NVIC_EXTI_IRQ(CLAP_BUTTON_PIN)); // enable interrupt
|
||||
printf("OK\n");
|
||||
|
||||
// main loop
|
||||
printf("command input: ready\n");
|
||||
|
@ -625,8 +650,29 @@ void main(void)
|
|||
frame_flag = false; // reset flag
|
||||
action = true; // action has been performed
|
||||
|
||||
// announce the scene and take using Morse code over the buzzer
|
||||
if (announce) {
|
||||
// display time and frame number
|
||||
char time[] = "00000000"; // time to display
|
||||
time[0] += (rtc_ds1307_time[2]/10)%10; // display hours
|
||||
time[1] += (rtc_ds1307_time[2])%10; // display hours
|
||||
time[1] |= 0x80; // dot for minutes on display
|
||||
time[2] += (rtc_ds1307_time[1]/10)%10; // display minutes
|
||||
time[3] += (rtc_ds1307_time[1])%10; // display minutes
|
||||
if (0==(rtc_seconds%2)) { // even seconds
|
||||
time[3] |= 0x80; // add dot for seconds
|
||||
}
|
||||
time[4] += (rtc_seconds/10)%10; // display seconds
|
||||
time[5] += (rtc_seconds)%10; // display seconds
|
||||
if (0==(frame_count%2)) { // even frames
|
||||
time[5] |= 0x80; // add dot for frame
|
||||
}
|
||||
time[6] += (frame_count/10)%10; // display frame
|
||||
time[7] += (frame_count)%10; // display frame
|
||||
led_max7219_text(time, 0); // display frame time on 1st display
|
||||
|
||||
// Morse the scene and take numbers over the buzzer
|
||||
if (morse_delay>0) {
|
||||
morse_delay--;
|
||||
} else if (0==morse_delay) {
|
||||
while (morse_i<LENGTH(morse)) {
|
||||
if (morse[morse_i]) { // skip empty codes
|
||||
if (morse_i%2) { // switch buzzer on for odd code
|
||||
|
@ -641,7 +687,7 @@ void main(void)
|
|||
}
|
||||
}
|
||||
if (morse_i>=LENGTH(morse)) { // all codes done
|
||||
announce = false; // announce finished
|
||||
morse_delay = -2; // Morse completed
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -758,24 +804,6 @@ void main(void)
|
|||
}
|
||||
}
|
||||
|
||||
// display time and frame number
|
||||
char time[] = "00000000"; // time to display
|
||||
time[0] += (rtc_ds1307_time[2]/10)%10; // display hours
|
||||
time[1] += (rtc_ds1307_time[2])%10; // display hours
|
||||
time[1] |= 0x80; // dot for minutes on display
|
||||
time[2] += (rtc_ds1307_time[1]/10)%10; // display minutes
|
||||
time[3] += (rtc_ds1307_time[1])%10; // display minutes
|
||||
if (0==(rtc_seconds%2)) { // even seconds
|
||||
time[3] |= 0x80; // add dot for seconds
|
||||
}
|
||||
time[4] += (rtc_seconds/10)%10; // display seconds
|
||||
time[5] += (rtc_seconds)%10; // display seconds
|
||||
if (0==(frame_count%2)) { // even frames
|
||||
time[5] |= 0x80; // add dot for frame
|
||||
}
|
||||
time[6] += (frame_count/10)%10; // display frame
|
||||
time[7] += (frame_count)%10; // display frame
|
||||
led_max7219_text(time, 0); // display frame time on 1st display
|
||||
}
|
||||
while (rtc_tick_flag) { // the external RTC ticked
|
||||
rtc_tick_flag = false; // reset flag
|
||||
|
@ -808,9 +836,18 @@ void main(void)
|
|||
}
|
||||
}
|
||||
while (keep_alive_flag) { // power switch is detecting movement to keep clapperboard running
|
||||
action = true; // action has been performed
|
||||
keep_alive_flag = false; // clear flag
|
||||
standby_timer = 0; // restart standby timer
|
||||
}
|
||||
while (clap_flag) { // clap detected
|
||||
action = true; // action has been performed
|
||||
clap_flag = false; // clear flag
|
||||
if (morse_delay<0) { // if beeping is not already queued
|
||||
encode_morse(); // encode scene and take number into Morse code
|
||||
morse_delay = FRAME_RATE; // wait 1 second
|
||||
}
|
||||
}
|
||||
if (action) { // go to sleep if nothing had to be done, else recheck for activity
|
||||
action = false;
|
||||
} else {
|
||||
|
@ -853,3 +890,10 @@ void EXTI_ISR(POWER_BUTTON_PIN)(void)
|
|||
exti_reset_request(EXTI(POWER_BUTTON_PIN)); // reset interrupt
|
||||
keep_alive_flag = true; // perform button action
|
||||
}
|
||||
|
||||
/** clap */
|
||||
void EXTI_ISR(CLAP_BUTTON_PIN)(void)
|
||||
{
|
||||
exti_reset_request(EXTI(CLAP_BUTTON_PIN)); // reset interrupt
|
||||
clap_flag = true; // perform clap action
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue