2016-01-17 14:54:54 +01:00
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
*/
/* Copyright (c) 2016 King Kévin <kingkevin@cuvoodoo.info> */
/* standard libraries */
# include <stdint.h> // standard integer types
# include <stdio.h> // standard I/O facilities
# include <stdlib.h> // standard utilities
# include <unistd.h> // standard streams
# include <errno.h> // error number utilities
2016-01-26 09:46:36 +01:00
# include <string.h> // stting utilities
2016-01-17 14:54:54 +01:00
/* STM32 (including CM3) libraries */
# include <libopencm3/stm32/rcc.h> // real-time control clock library
# include <libopencm3/stm32/gpio.h> // general purpose input output library
# include <libopencm3/cm3/scb.h> // vector table definition
2016-01-18 16:23:35 +01:00
# include <libopencmsis/core_cm3.h> // Cortex M3 utilities
2016-01-17 14:54:54 +01:00
2016-01-24 16:51:32 +01:00
# include <libopencm3/stm32/timer.h>
# include <libopencm3/cm3/nvic.h>
2016-01-22 16:22:47 +01:00
2016-01-17 14:54:54 +01:00
/* own libraries */
2016-01-24 17:26:53 +01:00
# include "global.h" // board definitions
2016-01-17 14:54:54 +01:00
# include "usart.h" // USART utilities
2016-01-18 16:23:35 +01:00
# include "usb_cdcacm.h" // USB CDC ACM utilities
2016-01-21 11:40:19 +01:00
# include "vfd.h" // VFD driver
2016-01-20 12:09:42 +01:00
2016-01-17 14:54:54 +01:00
/* default output (i.e. for printf) */
int _write ( int file , char * ptr , int len )
{
int i ;
if ( file = = STDOUT_FILENO | | file = = STDERR_FILENO ) {
for ( i = 0 ; i < len ; i + + ) {
if ( ptr [ i ] = = ' \n ' ) { // add carrier return before line feed. this is recommended for most UART terminals
usart_putchar_nonblocking ( ' \r ' ) ; // a second line feed doesn't break the display
2016-01-18 16:23:35 +01:00
cdcacm_putchar ( ' \r ' ) ; // a second line feed doesn't break the display
2016-01-17 14:54:54 +01:00
}
usart_putchar_nonblocking ( ptr [ i ] ) ; // send byte over USART
2016-01-18 16:23:35 +01:00
cdcacm_putchar ( ptr [ i ] ) ; // send byte over USB
2016-01-17 14:54:54 +01:00
}
return i ;
}
errno = EIO ;
return - 1 ;
}
static void gpio_setup ( void )
{
2016-01-19 12:15:46 +01:00
rcc_periph_clock_enable ( LED_RCC ) ; //enable clock for LED
2016-01-21 11:40:19 +01:00
gpio_set_mode ( LED_PORT , GPIO_MODE_OUTPUT_2_MHZ , GPIO_CNF_OUTPUT_PUSHPULL , LED_PIN ) ; // set LED pin to 'output push-pull'
2016-01-20 10:53:08 +01:00
}
2016-01-17 14:54:54 +01:00
int main ( void )
2016-01-17 15:03:10 +01:00
{
2016-01-17 14:54:54 +01:00
SCB_VTOR = ( uint32_t ) 0x08002000 ; // relocate vector table because of the bootloader
2016-01-19 12:15:46 +01:00
rcc_clock_setup_in_hse_8mhz_out_72mhz ( ) ; // use 8 MHz high speed external clock to generate 72 MHz internal clock
2016-01-17 14:54:54 +01:00
2016-01-19 12:15:46 +01:00
gpio_setup ( ) ; // setup main inputs/outputs
2016-01-17 15:03:10 +01:00
usart_setup ( ) ; // setup USART (for printing)
2016-01-22 16:22:47 +01:00
cdcacm_setup ( ) ; // setup USB CDC ACM (for printing)
2016-01-21 11:40:19 +01:00
vfd_setup ( ) ; // setup VFD
2016-01-18 16:23:35 +01:00
2016-01-17 14:54:54 +01:00
setbuf ( stdout , NULL ) ; // set standard out buffer to NULL to immediately print
setbuf ( stderr , NULL ) ; // set standard error buffer to NULL to immediately print
2016-01-26 09:46:36 +01:00
printf ( " welcome to the STM32F1 CuVoodoo vacuum fluorescent display driver \n " ) ;
2016-01-22 16:22:47 +01:00
2016-01-26 09:46:36 +01:00
printf ( " testing VFD \n " ) ;
2016-01-22 16:22:47 +01:00
vfd_on ( ) ; // switch on VFD
2016-01-25 00:46:09 +01:00
vfd_test ( ) ; // show all anodes
for ( uint32_t i = 0 ; i < 0x800000 ; i + + ) { // show for a bit of time
2016-01-20 12:09:42 +01:00
__asm__ ( " nop " ) ;
}
2016-01-25 00:46:09 +01:00
vfd_clear ( ) ; // clear all data
2016-01-24 21:54:42 +01:00
2016-01-26 09:46:36 +01:00
printf ( " scrolling message \n " ) ;
const char * message = " follow the white rabbit " ; // message to display (shifted by left-padded by VFD_MATRIX (12), right padded by VFD_MATRIX-VFD_DIGITS (2))
for ( uint8_t i = 0 ; i < strlen ( message ) ; i + + ) { // scroll through message (from right to left)
vfd_clear ( ) ; // clear display
for ( uint8_t j = i ; j < strlen ( message ) ; j + + ) { // display message
if ( j + 2 < ( uint8_t ) strlen ( message ) ) { // align VFD_MATRIX (12) to VFD_DIGITS (10)
vfd_digit ( j - i , message [ j + 2 ] ) ; // shift the matrix display
}
vfd_matrix ( j - i , message [ j ] ) ; // show digit
}
for ( uint32_t j = 0 ; j < 0x200000 ; j + + ) { // show for a bit of time
__asm__ ( " nop " ) ;
}
}
vfd_clear ( ) ; // clear all data
printf ( " showing animation \n " ) ;
// show rabbit + number animation
const uint8_t animation [ ] = { 2 , 3 , 2 , 3 , 2 , 3 , 7 , 6 , 7 , 6 , 7 , 6 } ; // rabbit animation (using pict5x7)
for ( uint8_t i = 0 ; i < sizeof ( animation ) & & i < VFD_MATRIX ; i + + ) {
vfd_clear ( ) ; // clear display
vfd_matrix ( i , 0x80 + animation [ i ] ) ; // show rabbit
for ( uint8_t j = 0 ; j < 50 ; j + + ) {
for ( uint8_t k = 0 ; k < VFD_DIGITS ; k + + ) {
vfd_digit ( k , ' 0 ' + ( rand ( ) % 10 ) ) ; // show (not very) random number
for ( uint32_t l = 0 ; l < 0x4000 ; l + + ) { // show for a bit of time
__asm__ ( " nop " ) ;
}
}
}
}
vfd_clear ( ) ; // clear all data
printf ( " type to display \n " ) ;
2016-01-25 10:29:32 +01:00
uint8_t vfd_place = 0 ; // the place on which the next character will be displayed on the VFD
bool vfd_flag = false ; // do something with the VFD
char c = 0 ; // the character to display
2016-01-21 11:40:19 +01:00
while ( true ) {
2016-01-17 15:03:10 +01:00
while ( usart_received ) { // echo every received character
2016-01-25 10:29:32 +01:00
c = usart_getchar ( ) ;
vfd_flag = true ; // display character
2016-01-17 15:03:10 +01:00
}
2016-01-18 16:23:35 +01:00
while ( cdcacm_received ) { // echo every received character
2016-01-25 10:29:32 +01:00
c = cdcacm_getchar ( ) ;
vfd_flag = true ; // display character
2016-01-18 16:27:51 +01:00
}
2016-01-21 13:06:51 +01:00
while ( vfd_flag ) {
2016-01-22 16:33:03 +01:00
vfd_flag = false ;
2016-01-26 09:46:36 +01:00
printf ( " %c " , c ) ; // transmit receive character
2016-01-25 10:29:32 +01:00
gpio_toggle ( LED_PORT , LED_PIN ) ; // toggle LED to show activity
if ( c = = ' \r ' | | c = = ' \n ' ) { // on newline
vfd_clear ( ) ; // clear display
vfd_place = 0 ; // restart from beginning
} else {
vfd_digit ( vfd_place , c ) ; // display character on digit
vfd_matrix ( vfd_place , c ) ; // display character on matrix
vfd_place + + ; // go to next place
}
}
2016-01-18 16:23:35 +01:00
__WFI ( ) ; // go to sleep
2016-01-17 14:54:54 +01:00
}
return 0 ;
}