add clap button

This commit is contained in:
King Kévin 2017-05-14 18:35:07 +02:00
parent f3e93d4c67
commit b6320b0ddf
1 changed files with 171 additions and 127 deletions

298
main.c
View File

@ -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
}