IniSat Modèle 1 Version 2 TP 4 : Etude d'un capteur Exo 1 : Lecture température Exo 2 : GPS, décodage données GGA

Soft_UART/soft_uart.cpp

Committer:
Giamarchi
Date:
2021-06-30
Revision:
1:ec64d7748431
Parent:
0:8b4bad2aad3f

File content as of revision 1:ec64d7748431:

// Software UART
//
// Generic software uart written in C, requiring a timer set to 3 times
// the baud rate, and two software read/write pins for the receive and
// transmit functions.
//
// * Received characters are buffered
// * putchar(), getchar(), kbhit() and flush_input_buffer() are available
// * There is a facility for background processing while waiting for input
//
// Colin Gittins, Software Engineer, Halliburton Energy Services
//
// The baud rate can be configured by changing the BAUD_RATE macro as
// follows:
//
// #define BAUD_RATE            19200.0
//
// The function init_uart() must be called before any comms can take place
//
// Interface routines required:
// 1. get_rx_pin_status()
//    Returns 0 or 1 dependent on whether the receive pin is high or low.
// 2. set_tx_pin_high()
//    Sets the transmit pin to the high state.
// 3. set_tx_pin_low()
//    Sets the transmit pin to the low state.
// 4. idle()
//    Background functions to execute while waiting for input.
// 5. timer_set( BAUD_RATE )
//    Sets the timer to 3 times the baud rate.
// 6. set_timer_interrupt( timer_isr )
//    Enables the timer interrupt.
//
// Functions provided:
// 1. void flush_input_buffer( void )
//    Clears the contents of the input buffer.
// 2. char kbhit( void )
//    Tests whether an input character has been received.
// 3. char getchar( void )
//    Reads a character from the input buffer, waiting if necessary.
// 4. void turn_rx_on( void )
//    Turns on the receive function.
// 5. void turn_rx_off( void )
//    Turns off the receive function.
// 6. void putchar( char )
//    Writes a character to the serial port.
#include "mbed.h"
#include <stdio.h>
 
#define BAUD_RATE       9600
#define IN_BUF_SIZE     256
 
#define TRUE 1
#define FALSE 0
 
static unsigned char        inbuf[IN_BUF_SIZE];
static unsigned char        qin = 0;
static unsigned char        qout = 0;
 
static char             flag_rx_waiting_for_stop_bit;
static char             flag_rx_off;
static char             rx_mask;
static char             flag_rx_ready;
static char             flag_tx_ready;
static char             timer_rx_ctr;
static char             timer_tx_ctr;
static char             bits_left_in_rx;
static char             bits_left_in_tx;
static char             rx_num_of_bits;
static char             tx_num_of_bits;
static int              internal_rx_buffer;
static int              internal_tx_buffer;
static int              user_tx_buffer;
 
DigitalOut TX(PA_4);
DigitalIn RX(PA_3);
Ticker ticker;

//Background functions to execute while waiting for input.
void idle(){
    wait_us(0.2);
}
 
//Sets the transmit pin to the high state.
void set_tx_pin_high() {
    TX = 1;
}
 
//Sets the transmit pin to the low state.
void set_tx_pin_low() {
    TX = 0;
}
 
//Returns 0 or 1 dependent on whether the receive pin is high or low
int get_rx_pin_status() {
    return RX.read();
}
 
void timer_isr(void) {
    
char mask, start_bit, flag_in;
 
// Transmitter Section
    if ( flag_tx_ready )
    {
        
        if ( --timer_tx_ctr <= 0 )
        {
            mask = internal_tx_buffer&1;
            internal_tx_buffer >>= 1;
            if ( mask )
            {
                set_tx_pin_high();          
            }
            else
            {
                set_tx_pin_low();
            }
            timer_tx_ctr = 3;
            if ( --bits_left_in_tx <= 0 )
            {
                flag_tx_ready = FALSE;
            }
        }
    }
// Receiver Section
    if ( flag_rx_off == FALSE )
        {
        if ( flag_rx_waiting_for_stop_bit )
            {
            if ( --timer_rx_ctr <= 0 )
                {
                flag_rx_waiting_for_stop_bit = FALSE;
                flag_rx_ready = FALSE;
                internal_rx_buffer &= 0xFF;
                if ( internal_rx_buffer != 0xC2 )
                    {
                    inbuf[qin] = internal_rx_buffer;
                    if ( ++qin >= IN_BUF_SIZE )
                        {
                            qin = 0;
                        }
                    }
                }
            }
        else        // rx_test_busy
            {
            if ( flag_rx_ready==FALSE )
                {
                start_bit = get_rx_pin_status();
// Test for Start Bit
                if ( start_bit == 0 )
                    {
                    flag_rx_ready = TRUE;
                    internal_rx_buffer = 0;
                    timer_rx_ctr = 4;
                    bits_left_in_rx = rx_num_of_bits;
                    rx_mask = 1;
                    }
                }
            else    // rx_busy
                {
                if ( --timer_rx_ctr<=0 )
                    {               // rcv
                    timer_rx_ctr = 3;
                    flag_in = get_rx_pin_status();
                    if ( flag_in )
                        {
                        internal_rx_buffer |= rx_mask;
                        }
                    rx_mask <<= 1;
                    if ( --bits_left_in_rx<=0 )
                        {
                        flag_rx_waiting_for_stop_bit = TRUE;
                        }
                    }
                }
            }
        }
    }
 
void Init_Soft_UART(void) {
    flag_tx_ready = FALSE;
    flag_rx_ready = FALSE;
    flag_rx_waiting_for_stop_bit = FALSE;
    flag_rx_off = FALSE;
    rx_num_of_bits = 8;     //10
    tx_num_of_bits = 10;     //10
 
    set_tx_pin_high();
    ticker.attach_us(&timer_isr, 1000000.0 / (BAUD_RATE * 3.0));
    }
 
char _getchar(void) {
    char        ch;
    do
        {
        while (qout == qin)
            {
            idle();
            }
        ch = inbuf[qout] & 0xFF;
        if (++qout >= IN_BUF_SIZE)
            {
            qout = 0;
            }
        }
    while (ch == 0x0A || ch == 0xC2);
    return(ch);
    }
 
void _putchar(char ch) {
    while ( flag_tx_ready );
    user_tx_buffer = ch;
 
// invoke_UART_transmit
    timer_tx_ctr = 3;
    bits_left_in_tx = tx_num_of_bits;
    internal_tx_buffer = (user_tx_buffer<<1) | 0x200;;
    flag_tx_ready = TRUE;
    }
 
void flush_input_buffer(void) {
    qin = 0;
    qout = 0;
    }
 
char kbhit(void) {
    return( qin!=qout );
    }
 
void turn_rx_on(void) {
    flag_rx_off = FALSE;
    }
 
void turn_rx_off(void) {
    flag_rx_off = TRUE;
    }
    
void printStr(char* str) {
    int i = 0;
    int len = strlen(str); 
    for(i = 0; i<len; i++){
        wait(0.01);
        _putchar(str[i]);
    }
}