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
/* 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 */
# include "main.h" // board definitions
# 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-21 13:06:51 +01:00
/* get the length of an array */
# define LENGTH(x) (sizeof(x) / sizeof((x)[0]))
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-24 16:51:32 +01:00
static void timer_setup ( void )
{
# define VFD_TIMER TIM2
# define VFD_TIMER_RCC RCC_TIM2
# define VFD_TIMER_IRQ NVIC_TIM2_IRQ
rcc_periph_clock_enable ( VFD_TIMER_RCC ) ; // enable clock for timer block
timer_reset ( VFD_TIMER ) ; // reset timer state
timer_set_mode ( VFD_TIMER , TIM_CR1_CKD_CK_INT , TIM_CR1_CMS_EDGE , TIM_CR1_DIR_UP ) ; // set timer mode, use undivided timer clock,edge alignment (simple count), and count up
timer_set_prescaler ( VFD_TIMER , ( SYSTEM_CLOCK_FREQ / ( 1 < < 16 ) ) - 1 ) ; // set the prescaler so this 16 bits timer overflows at 1Hz
//timer_set_period(0xffff/(VFD_DIGITS+VFD_MATRIX)/150); // set the refresh frequency
timer_set_period ( VFD_TIMER , 0xffff ) ;
timer_enable_irq ( VFD_TIMER , TIM_DIER_CC1IE ) ; // enable interrupt for timer
nvic_enable_irq ( VFD_TIMER_IRQ ) ; // allow interrupt for timer
timer_enable_counter ( VFD_TIMER ) ; // enable timer
}
void tim2_isr ( void )
{
if ( timer_get_flag ( VFD_TIMER , TIM_SR_UIF ) ) {
timer_clear_flag ( VFD_TIMER , TIM_SR_UIF ) ;
gpio_toggle ( LED_PORT , LED_PIN ) ;
}
}
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-24 16:51:32 +01:00
timer_setup ( ) ;
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-18 16:27:51 +01:00
printf ( " welcome to the STM32F1 CuVoodoo display driver \n " ) ;
2016-01-18 16:23:35 +01:00
2016-01-22 16:22:47 +01:00
vfd_on ( ) ; // switch on VFD
2016-01-21 11:52:59 +01:00
vfd_test ( ) ;
2016-01-20 12:09:42 +01:00
vfd_shift ( ) ;
2016-01-21 11:52:59 +01:00
for ( uint32_t i = 0 ; i < 0x800000 ; i + + ) {
2016-01-20 12:09:42 +01:00
__asm__ ( " nop " ) ;
}
2016-01-21 13:06:51 +01:00
vfd_clear ( ) ;
2016-01-21 11:52:59 +01:00
vfd_shift ( ) ;
2016-01-22 16:22:47 +01:00
vfd_digit ( 0 , ' 0 ' ) ;
vfd_shift ( ) ;
2016-01-20 12:09:42 +01:00
2016-01-21 13:06:51 +01:00
bool vfd_flag = false ;
for ( uint8_t i = 0 ; i < LENGTH ( vfd_digits ) ; i + + ) {
vfd_digits [ i ] = ' 0 ' + i ;
}
for ( uint8_t i = 0 ; i < LENGTH ( vfd_matrixs ) ; i + + ) {
vfd_matrixs [ i ] = ' A ' + i ;
}
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
printf ( " %c " , usart_getchar ( ) ) ; // transmit receive character
2016-01-21 13:06:51 +01:00
vfd_flag = true ;
2016-01-17 15:03:10 +01:00
}
2016-01-18 16:23:35 +01:00
while ( cdcacm_received ) { // echo every received character
printf ( " %c " , cdcacm_getchar ( ) ) ; // transmit receive character
2016-01-21 13:06:51 +01:00
vfd_flag = true ;
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-21 13:06:51 +01:00
gpio_toggle ( LED_PORT , LED_PIN ) ; // toggle LED
vfd_transmit ( ) ;
2016-01-18 16:23:35 +01:00
}
__WFI ( ) ; // go to sleep
2016-01-17 14:54:54 +01:00
}
return 0 ;
}