diff --git a/src/config.h b/src/config.h index a9a9c9a..27fef85 100644 --- a/src/config.h +++ b/src/config.h @@ -1,16 +1,14 @@ #ifndef SBCP_MASTER_CONFIG_H_ #define SBCP_MASTER_CONFIG_H_ -#define SBCP_MY_CLASS 0x00 ///< binary protocol class -#define SBCP_MY_ID 0x02 ///< binary protocol ID #define SBCP_FIRMWARE_VERSION 0x02 #define BAUDRATE 3310000 #define BAUDRATE_BUS BAUDRATE ///< UART baudrate for communication bus #define BAUDRATE_HOST BAUDRATE ///< UART baudrate for HOST-to-RS232 converter interface #endif // SBCP_MASTER_CONFIG_H_ diff --git a/src/led.c b/src/led.c index e2ea134..c33f914 100644 --- a/src/led.c +++ b/src/led.c @@ -1,167 +1,172 @@ #include "led.h" #include <sbcp-uc/gpio.h> #include "timer.h" #define NB_LEDS 4 //we set a frequency of blinking of 3 Hz #define DEFAULT_HALF_PERIOD 50/8 enum led_state { LED_OFF = 0x00, LED_ON = 0x01, LED_BLINKING = 0x02, }; struct led_def{ volatile enum led_state state; gpio gpio; unsigned int ticks_per_half_period; volatile unsigned int nb_ticks; volatile unsigned int nb_blink; volatile unsigned int current_nb_blinks; }; led leds[NB_LEDS]; led * green1 = &leds[0]; led * yellow = &leds[1]; led * green2 = &leds[2]; led * red = &leds[3]; void led_compute_and_apply_state(led * l, unsigned int nb_ticks) { unsigned char led_should_be_on = 0; switch (l->state) { case LED_OFF : led_should_be_on = 0; break; case LED_ON: led_should_be_on = 1; break; case LED_BLINKING : { l->nb_ticks += nb_ticks; if(l->nb_ticks >= 2 * l->ticks_per_half_period ) { l->nb_ticks -= 2 * l->ticks_per_half_period; ++l->current_nb_blinks; } if(l->current_nb_blinks >= 2 * l->nb_blink - 1 ) { l->current_nb_blinks = 0; } if(l->nb_ticks < l->ticks_per_half_period) { led_should_be_on = 1; } if (l->current_nb_blinks >= l->nb_blink) { led_should_be_on = 0; } break; } default: break; } if (led_should_be_on) { gpio_set(l->gpio); } else { gpio_clear(l->gpio); } } void led_init(){ green1->state = LED_ON; green1->gpio = gpio_create(GPIO_PORT_B , GPIO_PIN_14 , GPIO_OUTPUT); green1->ticks_per_half_period = DEFAULT_HALF_PERIOD; green1->nb_ticks = 0; green1->nb_blink = 1; green1->current_nb_blinks = 0; yellow->state = LED_OFF; yellow->gpio = gpio_create(GPIO_PORT_B , GPIO_PIN_15 , GPIO_OUTPUT); yellow->ticks_per_half_period = DEFAULT_HALF_PERIOD; yellow->nb_ticks = 0; yellow->nb_blink = 2; yellow->current_nb_blinks = 0; green2->state = LED_OFF; green2->gpio = gpio_create(GPIO_PORT_A , GPIO_PIN_0 , GPIO_OUTPUT); green2->ticks_per_half_period = DEFAULT_HALF_PERIOD; green2->nb_ticks = 0; green2->nb_blink = 2; green2->current_nb_blinks = 0; red->state = LED_OFF; red->gpio = gpio_create(GPIO_PORT_A , GPIO_PIN_1 , GPIO_OUTPUT); red->ticks_per_half_period = DEFAULT_HALF_PERIOD; red->nb_ticks = 0; red->nb_blink = 1; red->current_nb_blinks = 0; + unsigned int i = 0; + for(; i < NB_LEDS ; ++ i){ + led_compute_and_apply_state(&leds[i],1); + } + } void led_main(){ static ticks last_frame = 0; //we increment the frame every 50ms if( ticks_since(last_frame) >= us_to_ticks(20e3) ) { last_frame = current_time(); } else { //we only process each frame return; } unsigned int i = 0; for(; i < NB_LEDS ; ++ i){ led_compute_and_apply_state(&leds[i],1); } } void led_on(led * l) { l->state = LED_ON; } void led_off(led * l) { l->state = LED_OFF; } void led_toggle(led * l) { l->state = l->state == LED_OFF ? LED_ON : LED_OFF; } void led_blink(led * l) { if(l->state == LED_BLINKING) { return; } l->current_nb_blinks = 0; l->nb_ticks = 0; l->state = LED_BLINKING; } void led_blink_with_params(led * l, unsigned int nb_blink) { l->nb_blink = nb_blink; led_blink(l); } diff --git a/src/main.c b/src/main.c index 5cc1a07..34b9642 100644 --- a/src/main.c +++ b/src/main.c @@ -1,128 +1,129 @@ /* * Copyright (C) 2011-2013 Rico Moeckel, Alexandre Tuleu */ /** * \defgroup main MAIN * \brief Main file for the project. * This is the main file. * \author Rico Moeckel, Alexandre Tuleu * \version 2.0 * \date 2013-05-14 */ /*@{*/ /** * \file main.c * \brief Main file for the project. */ #include "config.h" #include <p33Fxxxx.h> #include "timer.h" #include "uart.h" #include "led.h" +#include "sbcp_host.h" +#include "sbcp_bus.h" /************************************************************************* * CONFIGURATION BITS * * With MPLAB X, microchip removed the ability to configure bits from * the GUI, and asked to do it directly from the code. It seems to be * a feature and not a lack of feature. So it will be better do to it * all the time from now ! *************************************************************************/ //Disable watch dog _FWDT(WDTPOST_PS32768 & WDTPRE_PR128 & WINDIS_OFF & FWDTEN_OFF) //pic started by external clock. _FOSC(POSCMD_NONE & OSCIOFNC_ON & FCKSM_CSECMD) //external clock _FOSCSEL(FNOSC_FRC & IESO_OFF) /** * \brief Initialization function for the clock of the microcontroller * * This function configures the clock system of the microcontroller to * use the internal oscillator as well as the PLL to run the clock at * maximum speed of 40MIPS. * */ void clock_init() { // Disable Watch Dog Timer RCONbits.SWDTEN=0; // Configure PLL prescaler, PLL postscaler, PLL divisor PLLFBD = 41; // M = 43 CLKDIVbits.PLLPOST=0; // N2 = 2 CLKDIVbits.PLLPRE=0; // N1 = 2 // Initiate Clock Switch to Internal FRC with PLL (NOSC = 0b001) __builtin_write_OSCCONH(0x01); __builtin_write_OSCCONL(0x01); // Wait for Clock switch to occur while (OSCCONbits.COSC != 0b001){}; // Wait for PLL to lock while(OSCCONbits.LOCK != 1) {}; } /** \brief Main initialization function for the microcontroller This * function calls all individual initialization functions of the * submodules. Register your local init functions here. Be careful * about the correct order of initializations. This function has to be * called inside the main routine before any other funtions. * * \param no parameters * \return no returns */ void main_init() { clock_init(); ADPCFG = 0xffff; // Set all Analog ports as Digital I/O TRISA = 0xffff; // Everything is input TRISB = 0xffff; // Everything is input timer_init(); led_init(); init_sbcp_host(); init_sbcp_bus(); } /** \brief Main function * * This function is the main function. It calls the main_init() * function and handles all main functions of the individual modules. * \param no parameters * \return int status */ int main() { - unsigned int i = 0; main_init(); while (1) { sbcp_process_host_tx(); sbcp_process_bus(); sbcp_process_host_rx(); led_main(); } return 0; } /*@}*/ diff --git a/src/packet.h b/src/packet.h index 5e395ea..1936790 100644 --- a/src/packet.h +++ b/src/packet.h @@ -1,89 +1,89 @@ #ifndef SBCP_MASTER_PACKETS_H_ #define SBCP_MASTER_PACKETS_H_ #include <sbcp-uc/sbcp_common.h> #include "timer.h" //defines the timeout time for a standard instruction to 1ms #define STD_SLAVE_RSP_TIMEOUT ( us_to_ticks(1e3) ) //defines the timeout time for a low latency instruction to 10us #define LLA_SLAVE_RESP_TIMEOUT ( us_to_ticks(10) ) typedef enum packet_rx_state { PCK_RX_UNITIALIZED = 0, PCK_RX_WAIT_FOR_HEADER_BYTE, PCK_RX_WAIT_FOR_FULL_HEADER, PCK_RX_WAIT_FOR_FULL_DATA, PCK_RX_FINISHED } packet_rx_state; typedef enum packet_rx_error { PCK_RX_NO_ERROR = 0, PCK_RX_TERR, PCK_RX_FERR, PCK_RX_PERR, PCK_RX_OERR } packet_rx_error; typedef struct packet_mdata { unsigned int dma_adr; volatile unsigned int * data; ticks start_rx_date; ticks end_tx_date; packet_rx_state rx_state; packet_rx_error rx_error; uint8_t id; } packet_mdata; //define the maximal time for getting a packet, #define MAX_PACKET_RX_TIME ( us_to_ticks(2 * 10 * SBCP_PACKET_SIZE / BAUDRATE * 1e6) ) /** * Returns if the rx of a packet timeouted. It occurs when the packet * has at least received one byte but not all and there is a * timeout. * \warning : Concurency UNSAFE */ #define pck_rx_timeouted(packet) ( ( (packet)->rx_state > PCK_RX_WAIT_FOR_HEADER_BYTE ) \ && ( (packet)->rx_state < PCK_RX_FINISHED ) \ && ( ( current_time() - (packet)->start_rx_date ) >= MAX_PACKET_RX_TIME ) ) // 1 if the std tx of a packet timeouted #define pck_std_tx_timeouted(packet) ( ( current_time() - (packet)->end_tx_date ) >= STD_SLAVE_RSP_TIMEOUT ) // 1 if the low latency tx of a packet timeouted #define pck_lla_tx_timeouted(packet) ( ( current_time() - (packet)->end_tx_date ) >= LLA_SLAVE_RSP_TIMEOUT ) #define pck_init_rx(packet) do{\ (packet)->rx_state = PCK_RX_WAIT_FOR_HEADER_BYTE; \ (packet)->rx_error = PCK_RX_NO_ERROR; \ }while(0) #define pck_start_header_rx(packet) do{\ (packet)->rx_state = PCK_RX_WAIT_FOR_FULL_HEADER; \ (packet)->start_rx_date = current_time(); \ }while(0) #define pck_start_data_rx(packet) do{\ (packet)->rx_state = PCK_RX_WAIT_FOR_FULL_DATA; \ }while(0) #define pck_finish_rx(packet) do{\ (packet)->rx_state = PCK_RX_FINISHED; \ }while(0) #define pck_clean_mdata(packet) do{\ (packet)->rx_state = PCK_RX_UNITIALIZED; \ }while(0) -#define pck_payload_size(packet) ( (packet)->data[SBCP_PAYLOAD_SIZE_POS] & (SBCP_PACKET_SIZE - 1 ) ) +#define pck_payload_size(packet) ( (packet)->data[SBCP_PAYLOAD_SIZE_POS] ) #define pck_byte_size(packet) ( pck_payload_size(packet) + SBCP_HEADER_SIZE ) #endif //SBCP_MASTER_PACKET_H_ diff --git a/src/sbcp_bus.c b/src/sbcp_bus.c index ef4c9b8..4192c79 100644 --- a/src/sbcp_bus.c +++ b/src/sbcp_bus.c @@ -1,82 +1,81 @@ #include "sbcp_bus.h" #include "sbcp_host.h" #include <sbcp-uc/buffers.h> volatile unsigned int __attribute__((space(dma))) bus_rx_buffer[SBCP_RX_BUFFER_SIZE]; typedef struct bus_data { - buffer_fifo dat_fifo,rdy_fifo; + buffer_fifo data_fifo,ready_fifo; packet_mdata pck_mdata[SBCP_FRAME_SIZE]; } bus_data; bus_data bus; void init_sbcp_bus(){ unsigned int i; for (i = 0 ; i < SBCP_FRAME_SIZE ; ++i){ bus.pck_mdata[i].data = &(bus_rx_buffer[i * SBCP_PACKET_SIZE]); bus.pck_mdata[i].dma_adr = __builtin_dmaoffset(bus_rx_buffer) + i * SBCP_PACKET_SIZE * 2; bus.pck_mdata[i].id = i; pck_clean_mdata(&(bus.pck_mdata[i])); } - buffer_fifo_set_empty(bus.dat_fifo); - buffer_fifo_set_empty(bus.rdy_fifo); + buffer_fifo_set_empty(bus.data_fifo); + buffer_fifo_set_empty(bus.ready_fifo); } void sbcp_process_bus(){ //todo : real implementation // this is a rather simple loopback implementation //we cannot process something if our fifo is full, we return - if ( buffer_fifo_full(bus.dat_fifo) ) { + if ( buffer_fifo_full(bus.data_fifo) ) { return; } //checks for incoming packet volatile packet_mdata * pck = next_host_packet(); if (pck != 0 ){ unsigned int i; //allocate some space in the ring buffer. it is possible because it is not full ! - buffer_fifo_increment_tail(bus.dat_fifo); - packet_mdata * loop_pck = &(bus.pck_mdata[bus.dat_fifo.tail]); + buffer_fifo_increment_tail(bus.data_fifo); + packet_mdata * loop_pck = &(bus.pck_mdata[bus.data_fifo.tail]); //simply copy the incoming packet . for (i = 0; i < pck_byte_size(pck); ++i){ loop_pck->data[i] = pck->data[i]; } // we do not need host data anymore - free_host_packet(pck); - + release_host_packet(pck); //copy the metadata too, to test error reporting loop_pck->rx_state = pck->rx_state; loop_pck->rx_error = pck->rx_error; //marks the packet as ready for downstream processing - buffer_fifo_increment_tail(bus.rdy_fifo); + buffer_fifo_increment_tail(bus.ready_fifo); } } volatile packet_mdata * next_bus_packet(){ - if( buffer_fifo_empty(bus.rdy_fifo) ) { + if( buffer_fifo_empty(bus.ready_fifo) ) { //no packet are present return 0; } - return &(bus.pck_mdata[bus.rdy_fifo.head]); + return &(bus.pck_mdata[bus.ready_fifo.head]); } -void free_bus_packet(volatile packet_mdata * pck ){ - if ( pck->id != bus.rdy_fifo.head ) { +void release_bus_packet(volatile packet_mdata * pck ){ + if ( pck->id != bus.ready_fifo.head ) { //TODO : report error return; } - buffer_fifo_increment_head(bus.rdy_fifo); - buffer_fifo_increment_head(bus.dat_fifo); + buffer_fifo_increment_head(bus.ready_fifo); + buffer_fifo_increment_head(bus.data_fifo); } diff --git a/src/sbcp_bus.h b/src/sbcp_bus.h index fc42571..04d02a2 100644 --- a/src/sbcp_bus.h +++ b/src/sbcp_bus.h @@ -1,19 +1,19 @@ #ifndef SBCP_MASTER_SBCP_BUS_H_ #define SBCP_MASTER_SBCP_BUS_H_ #include "packet.h" /// Initializes the sbcp bus processing void init_sbcp_bus(); /// Processes the sbcp bus void sbcp_process_bus(); /// Returns the next bus available packet, or 0 if none available volatile packet_mdata * next_bus_packet(); /// Frees the bus packet -void free_bus_packet(volatile packet_mdata * pck); +void release_bus_packet(volatile packet_mdata * pck); #endif //SBCP_MASTER_SBCP_BUS_H_ diff --git a/src/sbcp_host.h b/src/sbcp_host.h index 451df21..6e327c1 100644 --- a/src/sbcp_host.h +++ b/src/sbcp_host.h @@ -1,31 +1,31 @@ #ifndef SBCP_MASTER_SBCP_HOST_H_ #define SBCP_MASTER_SBCP_HOST_H_ #include "packet.h" //init all data void init_sbcp_host(); //main function to process the host rx state machine void sbcp_process_host_rx(); //main function to process the host tx void sbcp_process_host_tx(); /** * Gets the next available received packet. * \return 0 if no packet available or address to the next available packet */ volatile packet_mdata * next_host_packet(); /** * Releases the received packet. data should will be considered unsafe. */ -void release_host_packet(packet_mdata *); +void release_host_packet(volatile packet_mdata *); #endif //SBCP_MASTER_SBCP_HOST_RX_H_