From 086609f6c9c927144c89fd6487a4d455969255b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Sun, 21 May 2017 13:43:56 +0200 Subject: [PATCH] add final prototype documentation --- README.md | 65 ++++++++---- global.h | 2 +- main.c | 291 ++++++++++++++++++++++++++++-------------------------- 3 files changed, 197 insertions(+), 161 deletions(-) diff --git a/README.md b/README.md index 1f07129..62a4409 100644 --- a/README.md +++ b/README.md @@ -11,16 +11,17 @@ technology Clapperboards are used to synchronize audio and video tracks by clapping two wooden pieces. This is then visible on the video and the sharp sound is also present on the audio. -Using the scene and take number written on the clapperboard and spoke at the beginning of the recording it is possible to know which sound track corresponds to which video track. +Using the scene and take number written on the clapperboard and announced at the beginning of the recording it is possible to know which sound track corresponds to which video track. This clapper board improves this system with some features: -- use 7-segment displays to show scene and take number (instead of having to manually write and erase it on the board) -- show audio and video track numbers (number used in the file names or the recordings) -- show current time +- use 7-segment displays to show number, instead of having to manually write and erase it on the board + - episode, scene, and take + - two audio and video track numbers (number used in the file names or the recordings) + - current date, time, and frame number - automatically increment the take and recording numbers -The numbers on the board can be adjusted by hand using button switches. +The numbers on the board can be adjusted by hand using buttons. board ===== @@ -32,25 +33,28 @@ peripherals =========== - 1x 8-digit 7-segment display based on the MAX7219 to display the date -- 1x 8-digit 7-segment display based on the MAX7219 to display the time (hours, minutes, seconds, frame) +- 1x 8-digit 7-segment display based on the MAX7219 to display the time (hours, minutes, seconds) and frame number - 7x 4-digit 7-segment display based on the TM1637 to display recording information - - 1x to display the chapter/episode + - 1x to display the episode (or chapter) - 1x to display the scene - 1x to display the take - 2x to display the video file number - 2x to display the audio file number - 1x 16-channel multiplexer to communicate with the 7-segments individually - 8x2 button switches to adjust the recording numbers and seconds -- 1 button switch to detect clap -- 1x tilt sensor to detect movement -- 1x DS1307 RTC to keep track of the time +- 1x button switch to detect clap +- 1x shake sensor to detect movement and switch on the clapper board +- 1x DS1307 RTC to keep track of the time (using a tiny RTC module) +- 1x I2C EEPROM to save numbers (also present on the tiny RTC module) +- 1x power switching board (to switch off power completely) +- 1x battery + protection, charge, and 5V step up circuit connections =========== -Connect the peripherals the following way (peripheral signal; peripheral signal; micro-controller pin; micro-controller signal; comment): +Connect the peripherals the following way (peripheral signal; peripheral pin; micro-controller pin; micro-controller signal; comment): -- DS1307 RTC to get the date +- DS1307 RTC to get the date and EEPROM to save the numbers - VCC; 8; ; +5V; - GND; 4; ; GND; - SCL; 6; PB10; I2C2_SCL; @@ -65,8 +69,8 @@ Connect the peripherals the following way (peripheral signal; peripheral signal; - 7x TM1637 to show the recording numbers - VDD; 16; ; +5V; - GND; 1; ; GND; - - DIO; 17; PB7; GPIO; - - CLK; 18; 3-9; I0-I6; on analog multiplexed + - DIO; 17; PB7; GPIO; display with no clock signal will ignore data activity + - CLK; 18; 3-9; I0-I6; on analog multiplexer - 1x CD74HC4067 16-channel multiplexer - VCC; 24; ; +5V; - GND; 12; ; GND; @@ -76,13 +80,31 @@ Connect the peripherals the following way (peripheral signal; peripheral signal; - S1; 11; PB4; GPIO; to select output - S2; 14; PB5; GPIO; to select output - S3; 13; ; GND; - - I0; 9; 18; CLK; TM1637 for - - I1; 8; 18; CLK; TM1637 for - - I2; 7; 18; CLK; TM1637 for - - I3; 6; 18; CLK; TM1637 for - - I4; 5; 18; CLK; TM1637 for - - I5; 4; 18; CLK; TM1637 for - - I6; 3; 18; CLK; TM1637 for + - I0; 9; 18; CLK; TM1637 for audio 2 + - I1; 8; 18; CLK; TM1637 for video 2 + - I2; 7; 18; CLK; TM1637 for audio 1 + - I3; 6; 18; CLK; TM1637 for video 1 + - I4; 5; 18; CLK; TM1637 for episode + - I5; 4; 18; CLK; TM1637 for scene + - I6; 3; 18; CLK; TM1637 for take +- 1x power board (custom), including SW-18015P shake switch between collector of PNP and emitter (with pull-down resistor and diode between shake switch and emitter) + - GND; ; GND; step up voltage regulator; + - IN; ; 5V; step up voltage regulator; + - OUT; ; +5V; all other peripherals + - base of PNP; SWITCH; PB8; to control power to all peripherals + - not-collector connected pin of shake switch; ACTIVITY; PB1; to detect power-up activity +- 1x clap switch + - pin 1; 1; ; GND; + - pin 2; 2; PB14; ; to detect clapping action (add pull-up resistor to improve detection) +- 16x buttons, in a 4x4 matrix + - 4x row 0 buttons; ; PA0; ; row 0 + - 4x row 1 buttons; ; PA1; ; row 1 + - 4x row 2 buttons; ; PA2; ; row 2 + - 4x row 3 buttons; ; PA3; ; row 3 + - 4x column 0 buttons; ; PA4; ; column 0, with a pull-down resistor + - 4x column 1 buttons; ; PA5; ; column 1, with a pull-down resistor + - 4x column 2 buttons; ; PA6; ; column 2, with a pull-down resistor + - 4x column 3 buttons; ; PA15; ; column 3, with a pull-down resistor All pins are configured using `define`s in the corresponding source code. @@ -124,6 +146,7 @@ USB --- The firmware offers serial communication over USART1 and USB (using the CDC ACM device class). +Date and time can be set over serial. You can also reset the board by setting the serial width to 5 bits over USB. To reset the board run `make reset`. diff --git a/global.h b/global.h index bf35164..49df00c 100644 --- a/global.h +++ b/global.h @@ -20,7 +20,7 @@ #pragma once /** enable debugging functionalities */ -#define DEBUG true +#define DEBUG false /** get the length of an array */ #define LENGTH(x) (sizeof(x) / sizeof((x)[0])) diff --git a/main.c b/main.c index 0ebde84..94c7445 100644 --- a/main.c +++ b/main.c @@ -56,22 +56,27 @@ volatile bool keep_alive_flag = false; /**< flag to restart shutdown counter on volatile bool clap_flag = false; /**< flag set on clap */ /** @} */ +#define POWER_SWITCH_PORT B /**< port to switch power of all devices (including this micro-controller) */ +#define POWER_SWITCH_PIN 8 /**< pin to switch power of all devices (including this micro-controller) */ +#define POWER_BUTTON_PORT B /**< port to detect power switching activity by shaking (to keep alive) */ +#define POWER_BUTTON_PIN 1 /**< pin to detect power switching activity by shaking (to keep alive) */ + #define SQUARE_WAVE_PORT B /**< port connected to RTC DS1307 square wave output */ #define SQUARE_WAVE_PIN 0 /**< pin connected to RTC DS1307 square wave output */ -volatile uint8_t rtc_seconds = 0; /**< number of seconds passed incremented by the square wave */ +volatile uint8_t rtc_seconds = 0; /**< number of seconds passed, incremented by the square wave */ #define STANDBY_TIMEOUT 30 /**< number of seconds after last shake before going down */ -volatile uint16_t standby_timer = 0; /**< number of seconds since last wake-up/activity */ +volatile uint16_t standby_timer = 0; /**< number of seconds since last power-up activity (using shake sensor) */ #define FRAME_TIMER 2 /**< timer to count frame time */ -#define FRAME_RATE 25 /**< frame rate */ +#define FRAME_RATE 25 /**< frame rate in frames per second */ volatile uint8_t frame_count = 0; /**< number of frames passed */ #define BUZZER_TIMER 1 /**< timer to generate scene and take count */ -#define BUZZER_1_PORT A /**< use timer 1 channel 1 (and it's negative) to driver buzzer */ -#define BUZZER_1_PIN 7 /**< use timer 1 channel 1 (and it's negative) to driver buzzer */ -#define BUZZER_2_PORT A /**< use timer 1 channel 1 (and it's negative) to driver buzzer */ -#define BUZZER_2_PIN 8 /**< use timer 1 channel 1 (and it's negative) to driver buzzer */ +#define BUZZER_1_PORT A /**< use timer channel 1 (and it's negative) to driver buzzer */ +#define BUZZER_1_PIN 7 /**< use timer channel 1 (and it's negative) to driver buzzer */ +#define BUZZER_2_PORT A /**< use timer channel 1 (and it's negative) to driver buzzer */ +#define BUZZER_2_PIN 8 /**< use timer channel 1 (and it's negative) to driver buzzer */ #define MUX_EN_PORT B /**< port to enable multiplexer */ #define MUX_EN_PIN 9 /**< pin to enable multiplexer */ @@ -102,11 +107,6 @@ struct number_t numbers[] = { #define BUTTON_SECONDS_UP 9 /**< which of the 16 buttons is to increment the seconds */ #define BUTTON_SECONDS_DOWN 13 /**< which of the 16 buttons is to decrement the seconds */ -#define POWER_SWITCH_PORT B /**< port to switch power of all devices (including this micro-controller) */ -#define POWER_SWITCH_PIN 8 /**< pin to switch power of all devices (including this micro-controller) */ -#define POWER_BUTTON_PORT B /**< port to detect power switching activity (to keep alive) */ -#define POWER_BUTTON_PIN 1 /**< pin to detect power switching activity (to keep alive) */ - // buttons to adjust numbers and seconds (mutliplexed in a 4x4 matrix) #define BUTTONS_DRIVE_PORT A /**< port used to drive the buttons rows */ #define BUTTONS_DRIVE_PIN0 0 /**< pin used to drive buttons row 0 */ @@ -122,7 +122,7 @@ struct number_t numbers[] = { #define CLAP_BUTTON_PORT B /**< port for button to detect clap action */ #define CLAP_BUTTON_PIN 14 /**< port for button to detect clap action */ -/** Morse code variables, to buzz scene and take */ +/** Morse code variables, to buzz/beep 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 */ @@ -237,8 +237,8 @@ error: return; } -/** select output for TM1637 display using the multiplexer - * @param[in] output clock output +/** select clock output for TM1637 display using the analog multiplexer + * @param[in] output clock output channel */ static void mux_select(uint8_t output) { @@ -292,21 +292,21 @@ static void mux_select(uint8_t output) } } -/** encode scene and take into Morse code (in morse) */ +/** encode scene and take into Morse code (in morse variable) */ static void encode_morse(void) { - // encode numbers (scene and take) in Morse code + // numbers (scene and take) to encode in Morse code uint16_t morse_numbers[] = {numbers[1].number, numbers[2].number}; printf("morsing scene: %u, take: %u\n", morse_numbers[0], morse_numbers[1]); for (uint8_t morse_number=0; morse_number0) { - morse_delay--; - } else if (0==morse_delay) { - while (morse_i0) { // not ready to Morse + morse_delay--; // still wait before Morsing + } else if (0==morse_delay) { // ready to Morse + while (morse_i=LENGTH(morse)) { // all codes done morse_delay = -2; // Morse completed + gpio_clear(GPIO(BUZZER_1_PORT), GPIO(BUZZER_1_PIN)); // ensure it's not beeping + gpio_clear(GPIO(BUZZER_2_PORT), GPIO(BUZZER_2_PIN)); // ensure it's not beeping } } // read button inputs (drive and read each row since they are multiplexed) - uint16_t buttons_new = 0; + uint16_t buttons_new = 0; // to save new button states + // drive row 0 gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUTTONS_DRIVE_PIN0)); gpio_set(GPIO(BUTTONS_DRIVE_PORT), GPIO(BUTTONS_DRIVE_PIN0)); gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUTTONS_DRIVE_PIN1)|GPIO(BUTTONS_DRIVE_PIN2)|GPIO(BUTTONS_DRIVE_PIN3)); + // read all columns for this row buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN0)) ? 1 : 0)<<0); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN1)) ? 1 : 0)<<1); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN2)) ? 1 : 0)<<2); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN3)) ? 1 : 0)<<3); + // drive row 1 gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUTTONS_DRIVE_PIN1)); gpio_set(GPIO(BUTTONS_DRIVE_PORT), GPIO(BUTTONS_DRIVE_PIN1)); gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUTTONS_DRIVE_PIN0)|GPIO(BUTTONS_DRIVE_PIN2)|GPIO(BUTTONS_DRIVE_PIN3)); + // read all columns for this row buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN0)) ? 1 : 0)<<4); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN1)) ? 1 : 0)<<5); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN2)) ? 1 : 0)<<6); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN3)) ? 1 : 0)<<7); + // drive row 2 gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUTTONS_DRIVE_PIN2)); gpio_set(GPIO(BUTTONS_DRIVE_PORT), GPIO(BUTTONS_DRIVE_PIN2)); gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUTTONS_DRIVE_PIN0)|GPIO(BUTTONS_DRIVE_PIN1)|GPIO(BUTTONS_DRIVE_PIN3)); + // read all columns for this row buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN0)) ? 1 : 0)<<8); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN1)) ? 1 : 0)<<9); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN2)) ? 1 : 0)<<10); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN3)) ? 1 : 0)<<11); + // drive row 3 gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(BUTTONS_DRIVE_PIN3)); gpio_set(GPIO(BUTTONS_DRIVE_PORT), GPIO(BUTTONS_DRIVE_PIN3)); gpio_set_mode(GPIO(BUTTONS_DRIVE_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(BUTTONS_DRIVE_PIN0)|GPIO(BUTTONS_DRIVE_PIN1)|GPIO(BUTTONS_DRIVE_PIN2)); + // read all columns for this row buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN0)) ? 1 : 0)<<12); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN1)) ? 1 : 0)<<13); buttons_new |= ((gpio_get(GPIO(BUTTONS_READ_PORT), GPIO(BUTTONS_READ_PIN2)) ? 1 : 0)<<14); @@ -733,17 +742,19 @@ void main(void) buttons = buttons_new; // save new state if (buttons_diff) { // only do something if there is a change //printf("button pressed: %016b\n", buttons); - for (uint8_t number=0; number>8, numbers[number].number}; - if (!rtc_ds1307_write_rom(number*LENGTH(bytes), bytes, LENGTH(bytes))) { - printf("could not set number on EEPROM\n"); + // display numbers on TM1637 + mux_select(numbers[number].display); + if (0xffff==numbers[number].number) { + led_tm1637_off(); + } else { + led_tm1637_number(numbers[number].number); + } + // save number + uint8_t bytes[2] = {numbers[number].number>>8, numbers[number].number}; + if (!rtc_ds1307_write_rom(number*LENGTH(bytes), bytes, LENGTH(bytes))) { + printf("could not set number on EEPROM\n"); + } } } if ((buttons_diff&(1<=60) { @@ -789,6 +801,7 @@ void main(void) } } } else if (buttons_diff&(1<0) { rtc_ds1307_time[0] -= 1; @@ -804,7 +817,7 @@ void main(void) } } rtc_seconds = rtc_ds1307_time[0]; // save seconds since this is only updated every minute - if (!rtc_ds1307_write_time(rtc_ds1307_time[0], rtc_ds1307_time[1], rtc_ds1307_time[2], rtc_ds1307_time[3], rtc_ds1307_time[4], rtc_ds1307_time[5], rtc_ds1307_time[6])) { + if (!rtc_ds1307_write_time(rtc_ds1307_time[0], rtc_ds1307_time[1], rtc_ds1307_time[2], rtc_ds1307_time[3], rtc_ds1307_time[4], rtc_ds1307_time[5], rtc_ds1307_time[6])) { // save adjusted time to DS1307 printf("could not set time on DS1307: resetting\n"); rtc_ds1307_setup(); // resetting peripheral } @@ -820,7 +833,7 @@ void main(void) if (standby_timer>=STANDBY_TIMEOUT) { // standby timeout complete // go into standby mode printf("shutting down\n"); - // increment and save take if there has been a clap + // increment and save take and video/audio numbers if there has been a clap if (-2==morse_delay) { morse_delay = -1; // prevent incrementing multiple times uint8_t bytes[LENGTH(numbers)*2] = {0}; // all numbers to write again in EEPROM @@ -851,7 +864,7 @@ void main(void) rtc_ds1307_time = rtc_ds1307_read_time(); // get time/date from external RTC if (rtc_ds1307_time==NULL) { printf("could not get time from DS1307: resetting\n"); - rtc_ds1307_setup(); // resetting periph + rtc_ds1307_setup(); // resetting peripheral } else { rtc_seconds = rtc_ds1307_time[0]; // get actual number of seconds if (0==rtc_ds1307_time[1] && 0==rtc_ds1307_time[2]) { // new day arrived