Urbanite: Parking aid system
fsm_ultrasound.c File Reference

Ultrasound sensor FSM main file. More...

#include <stdlib.h>
#include <string.h>
#include "port_ultrasound.h"
#include "port_system.h"
#include "fsm.h"
#include "fsm_ultrasound.h"

Data Structures

struct  fsm_ultrasound_t
 Structure to define the Ultrasound FSM. More...
 

Functions

int _compare (const void *a, const void *b)
 Compare function to sort arrays. More...
 
static bool check_on (fsm_t *p_this)
 Check if the ultrasound sensor is active and ready to start a new measurement. More...
 
static bool check_off (fsm_t *p_this)
 Check if the ultrasound sensor has been set to be inactive (OFF). More...
 
static bool check_trigger_end (fsm_t *p_this)
 Check if the ultrasound sensor has finished the trigger signal. More...
 
static bool check_echo_init (fsm_t *p_this)
 Check if the ultrasound sensor has received the init (rising edge in the input capture) of the echo signal. More...
 
static bool check_echo_received (fsm_t *p_this)
 Check if the ultrasound sensor has received the end (falling edge in the input capture) of the echo signal. More...
 
static bool check_new_measurement (fsm_t *p_this)
 Check if a new measurement is ready. More...
 
static void do_start_measurement (fsm_t *p_this)
 Start a measurement of the ultrasound transceiver for the first time after the FSM is started. More...
 
static void do_start_new_measurement (fsm_t *p_this)
 Start a new measurement of the ultrasound transceiver. More...
 
static void do_stop_trigger (fsm_t *p_this)
 Stop the trigger signal of the ultrasound sensor. More...
 
static void do_set_distance (fsm_t *p_this)
 Set the distance measured by the ultrasound sensor. More...
 
static void do_stop_measurement (fsm_t *p_this)
 Stop the ultrasound sensor. More...
 
static void fsm_ultrasound_init (fsm_ultrasound_t *p_fsm_ultrasound, uint32_t ultrasound_id)
 Initialize a ultrasound FSM. More...
 
fsm_ultrasound_tfsm_ultrasound_new (uint32_t ultrasound_id)
 Create a new ultrasound FSM. More...
 
void fsm_ultrasound_destroy (fsm_ultrasound_t *p_fsm)
 Destroy an ultrasound FSM. More...
 
void fsm_ultrasound_fire (fsm_ultrasound_t *p_fsm)
 Fire the ultrasound FSM. More...
 
uint32_t fsm_ultrasound_get_distance (fsm_ultrasound_t *p_fsm)
 Return the distance of the last object detected by the ultrasound sensor.a64l. More...
 
void fsm_ultrasound_stop (fsm_ultrasound_t *p_fsm)
 Stop the ultrasound sensor. More...
 
void fsm_ultrasound_start (fsm_ultrasound_t *p_fsm)
 Start the ultrasound sensor. More...
 
bool fsm_ultrasound_get_status (fsm_ultrasound_t *p_fsm)
 Get the status of the ultrasound transceiver FSM. More...
 
void fsm_ultrasound_set_status (fsm_ultrasound_t *p_fsm, bool status)
 Set the status of the ultrasound sensor. true means that the ultrasound sensor is active and a distance measurement must be performed. false means that the ultrasound sensor is inactive. More...
 
bool fsm_ultrasound_get_ready (fsm_ultrasound_t *p_fsm)
 Get the ready flag of the trigger signal in the ultrasound HW. More...
 
bool fsm_ultrasound_get_new_measurement_ready (fsm_ultrasound_t *p_fsm)
 Return the flag that indicates if a new measurement is ready. More...
 
fsm_t * fsm_ultrasound_get_inner_fsm (fsm_ultrasound_t *p_fsm)
 Get the inner FSM of the ultrasound. More...
 
uint32_t fsm_ultrasound_get_state (fsm_ultrasound_t *p_fsm)
 Get the state of the ultrasound FSM. More...
 
void fsm_ultrasound_set_state (fsm_ultrasound_t *p_fsm, int8_t state)
 Set the state of the ultrasound FSM. More...
 
bool fsm_ultrasound_check_activity (fsm_ultrasound_t *p_fsm)
 Check if the ultrasound sensor is doing a distance measurement. More...
 

Variables

static fsm_trans_t fsm_trans_ultrasound []
 Array representing the transitions table of the FSM ultrasound. More...
 

Detailed Description

Ultrasound sensor FSM main file.

Author
Sistemas Digitales II
Date
2025-01-01

Function Documentation

◆ _compare()

int _compare ( const void *  a,
const void *  b 
)

Compare function to sort arrays.

This function is used to compare two elements. It will be used for the qsort() function to sort the array of distances.

Parameters
aPointer to the first element to compare.
bPointer to the second element to compare.
Returns
int Result of the comparison.

◆ check_echo_init()

static bool check_echo_init ( fsm_t *  p_this)
static

Check if the ultrasound sensor has received the init (rising edge in the input capture) of the echo signal.

TODO alumnos:

✅ 1. Call function port_ultrasound_get_echo_init_tick() to retrieve the time tick of the echo signal
✅ 2. Return true if the time tick is higher than 0. Otherwise, return false

Parameters
p_thisPointer to an fsm_t struct that contains an fsm_ultrasound_t.
Returns
true
false

◆ check_echo_received()

static bool check_echo_received ( fsm_t *  p_this)
static

Check if the ultrasound sensor has received the end (falling edge in the input capture) of the echo signal.

TODO alumnos:

✅ 1. Call function port_ultrasound_get_echo_received() to retrieve and return the status of the echo signal: it will be true if both the init and end ticks have been received.

Parameters
p_thisPointer to an fsm_t struct that contains an fsm_ultrasound_t.
Returns
true
false

◆ check_new_measurement()

static bool check_new_measurement ( fsm_t *  p_this)
static

Check if a new measurement is ready.

TODO alumnos:

✅ 1. Call function port_ultrasound_get_trigger_ready() to retrieve and return the status of the trigger signal. If it is true means that the ultrasound sensor is ready to start a new measurement.

Parameters
p_thisPointer to an fsm_t struct that contains an fsm_ultrasound_t.
Returns
true
false

◆ check_off()

static bool check_off ( fsm_t *  p_this)
static

Check if the ultrasound sensor has been set to be inactive (OFF).

TODO alumnos:

✅ 1. Return the inverse of the flag status

Parameters
p_thisPointer to an fsm_t struct that contains an fsm_ultrasound_t.
Returns
true
false

◆ check_on()

static bool check_on ( fsm_t *  p_this)
static

Check if the ultrasound sensor is active and ready to start a new measurement.

TODO alumnos:

✅ 1. Call function port_ultrasound_get_trigger_ready() and retrieve the status of the trigger signal
✅ 2. Return true if the ultrasound sensor flag is active and ready to start a new measurement. Otherwise, return false

Parameters
p_thisPointer to an fsm_t struct that contains an fsm_ultrasound_t.
Returns
true
false

◆ check_trigger_end()

static bool check_trigger_end ( fsm_t *  p_this)
static

Check if the ultrasound sensor has finished the trigger signal.

TODO alumnos:

✅ 1. Call function port_ultrasound_get_trigger_end() and retrieve the status of the trigger signal and return it. It will be true if the time to trigger the ultrasound sensor has finished.

Parameters
p_thisPointer to an fsm_t struct that contains an fsm_ultrasound_t.
Returns
true
false

◆ do_set_distance()

static void do_set_distance ( fsm_t *  p_this)
static

Set the distance measured by the ultrasound sensor.

This function is called when the ultrasound sensor has received the echo signal. It calculates the distance in cm and stores it in the array of distances.

When the array is full, it computes the median of the array and resets the index of the array.

TODO alumnos:

✅ 1. Retrieve the echo init tick, echo end tick, and echo overflows from the ultrasound sensor.
✅ 2. Calculate the time that the sound has taken to go back and forth by using the equation that relates the time with the distance and the number of overflows.
✅ 3. Calculate the distance in cm taking into account the speed of sound.
✅ 4. Store the distance in the array of distances in the position of the index.
✅ 5. If the array is full, sort the array by calling the function qsort(). This function sorts the array in ascending order and receives the array, the number of elements of the array (FSM_ULTRASOUND_NUM_MEASUREMENTS), the size of each element (sizeof(uint32_t)), and the compare function.

qsort(p_fsm->distance_arr, FSM_ULTRASOUND_NUM_MEASUREMENTS, sizeof(uint32_t), _compare);

✅ 6. If the array is full, compute the median of the array and store it in the field distance_cm. Make sure to consider if the number of measurements FSM_ULTRASOUND_NUM_MEASUREMENTS is even or odd.
✅ 7. If the array is full, set the flag new_measurement to indicate that a new measurement is ready.
✅ 8. Increase the distance index. If the index is higher or equal FSM_ULTRASOUND_NUM_MEASUREMENTS, reset the index. You can use the modulo operator to do this.
✅ 9. Call function port_ultrasound_stop_echo_timer() to stop the timer that controls the input capture of the echo signal.
✅ 10. Call function port_ultrasound_reset_echo_ticks() to reset the time ticks of the echo signal.

Parameters
p_thisPointer to an fsm_t struct than contains an fsm_ultrasound_t.

◆ do_start_measurement()

static void do_start_measurement ( fsm_t *  p_this)
static

Start a measurement of the ultrasound transceiver for the first time after the FSM is started.

TODO alumnos:

✅ 1. Call function port_ultrasound_start_measurement() with the right parameters to start a new measurement.

Parameters
p_thisPointer to an fsm_t struct than contains an fsm_ultrasound_t.

◆ do_start_new_measurement()

static void do_start_new_measurement ( fsm_t *  p_this)
static

Start a new measurement of the ultrasound transceiver.

This function is called when the ultrasound sensor has finished a measurement and is ready to start a new one.

TODO alumnos:

✅ 1. Call function do_start_measurement() to start a new measurement.

Parameters
p_thisPointer to an fsm_t struct than contains an fsm_ultrasound_t.

◆ do_stop_measurement()

static void do_stop_measurement ( fsm_t *  p_this)
static

Stop the ultrasound sensor.

This function is called when the ultrasound sensor is stopped. It stops the ultrasound sensor and resets the echo ticks.

TODO alumnos:

✅ 1. Call function port_ultrasound_stop_ultrasound() with the right parameters to stop the ultrasound sensor.

Parameters
p_thisPointer to an fsm_t struct than contains an fsm_ultrasound_t.

◆ do_stop_trigger()

static void do_stop_trigger ( fsm_t *  p_this)
static

Stop the trigger signal of the ultrasound sensor.

This function is called when the time to trigger the ultrasound sensor has finished. It stops the trigger signal and the trigger timer.

TODO alumnos:

✅ 1. Call function port_ultrasound_stop_trigger_timer() to stop the timer that controls the trigger signal.
✅ 2. Call function port_ultrasound_set_trigger_end() to set the trigger signal to low.

Parameters
p_thisPointer to an fsm_t struct than contains an fsm_ultrasound_t.

◆ fsm_ultrasound_check_activity()

bool fsm_ultrasound_check_activity ( fsm_ultrasound_t p_fsm)

Check if the ultrasound sensor is doing a distance measurement.

The ultrasound sensor is always inactive because all the transitions are due to HW interrupts.

TODO alumnos Version 4:

✅ 1. Return false always.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
Returns
true
false

◆ fsm_ultrasound_destroy()

void fsm_ultrasound_destroy ( fsm_ultrasound_t p_fsm)

Destroy an ultrasound FSM.

This function destroys an ultrasound transceiver FSM and frees the memory.

TODO alumnos:

✅ 1. Implement this function analogously to the fsm_button_destroy() function.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.

◆ fsm_ultrasound_fire()

void fsm_ultrasound_fire ( fsm_ultrasound_t p_fsm)

Fire the ultrasound FSM.

This function is used to fire the ultrasound FSM. It is used to check the transitions and execute the actions of the ultrasound FSM.

TODO alumnos:

✅ 1. Call function fsm_fire() with the received pointer to fsm_t

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.

◆ fsm_ultrasound_get_distance()

uint32_t fsm_ultrasound_get_distance ( fsm_ultrasound_t p_fsm)

Return the distance of the last object detected by the ultrasound sensor.a64l.

The function also resets the field new_measurement to indicate that the distance has been read.

TODO alumnos:

✅ 1. Retrieve and return the field distance_cm.
✅ 2. Reset the field new_measurement.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
Returns
uint32_t Distance measured by the ultrasound sensor in centimeters.

◆ fsm_ultrasound_get_inner_fsm()

fsm_t* fsm_ultrasound_get_inner_fsm ( fsm_ultrasound_t p_fsm)

Get the inner FSM of the ultrasound.

This function returns the inner FSM of the ultrasound.

    💡 This function is important because the struct is private and external functions such as those of the unit tests cannot access the inner FSM directly.

TODO alumnos:

✅ 1. Return the address of the f field of the struct.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
Returns
fsm_t* Pointer to the inner FSM.

◆ fsm_ultrasound_get_new_measurement_ready()

bool fsm_ultrasound_get_new_measurement_ready ( fsm_ultrasound_t p_fsm)

Return the flag that indicates if a new measurement is ready.

TODO alumnos:

✅ 1. Retrieve and return the field new_measurement.

Parameters
p_fsmPointer to the ultrasound FSM.
Returns
true
false

◆ fsm_ultrasound_get_ready()

bool fsm_ultrasound_get_ready ( fsm_ultrasound_t p_fsm)

Get the ready flag of the trigger signal in the ultrasound HW.

This function returns the ready flag of trigger signal in the ultrasound HW. This function might be used for testing and debugging purposes.

TODO alumnos:

✅ 1. Call function port_ultrasound_get_trigger_ready() with the ultrasound ID and return the result.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
Returns
true If the port indicates that the trigger signal is ready to start a new measurement.
false If the port indicates that the trigger signal is not ready to start a new measurement.

◆ fsm_ultrasound_get_state()

uint32_t fsm_ultrasound_get_state ( fsm_ultrasound_t p_fsm)

Get the state of the ultrasound FSM.

This function returns the current state of the ultrasound FSM.

    💡 This function is important because the struct is private and external functions such as those of the unit tests cannot access the state of the FSM directly.

TODO alumnos:

✅ 1. Retrieve and return the field current_state of the FSM (field f of the struct).

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
Returns
uint32_t Current state of the ultrasound FSM.

◆ fsm_ultrasound_get_status()

bool fsm_ultrasound_get_status ( fsm_ultrasound_t p_fsm)

Get the status of the ultrasound transceiver FSM.

This function returns the status of the ultrasound. This function might be used for testing and debugging purposes.

TODO alumnos:

✅ 1. Retrieve and return the field status.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
Returns
true If the ultrasound system has been indicated to be active.
false If the ultrasound system has been indicated to be paused.

◆ fsm_ultrasound_init()

static void fsm_ultrasound_init ( fsm_ultrasound_t p_fsm_ultrasound,
uint32_t  ultrasound_id 
)
static

Initialize a ultrasound FSM.

This function initializes the default values of the FSM struct and calls to the port to initialize the associated HW given the ID.

The FSM stores the distance of the last ultrasound trigger. The user should ask for it using the function fsm_ultrasound_get_distance().

The FSM contains information of the ultrasound ID. This ID is a unique identifier that is managed by the user in the port. That is where the user provides identifiers and HW information for all the ultrasounds on his system. The FSM does not have to know anything of the underlying HW.

Note
Both unit and integration tests (example) are provided for this ultrasound library are available in this GitHub repository: https://github.com/sdg2DieUpm/urbanite/tree/urbanite_v2_test

TODO alumnos:

✅ 1. Call the fsm_init() to initialize the FSM. Pass the address of the fsm_t struct and the transition table.
✅ 2. Initialize the fields all the fields of the p_fsm: distance_cm, distance_idx, and distance_arr, to 0. To do the later, you can use the function memset(). ✅ 3. Initialize the field status and new_measurement to false.
✅ 4. Call function port_ultrasound_init() to initialize the HW of the ultrasound sensor.

Note
The main program and the port are the only ones that manage and stablish the ID. The ultrasound FSM acts as a man-in-the-middle but this library does not handles the ultrasound IDs.
Parameters
p_fsm_ultrasoundPointer to the ultrasound FSM.
ultrasound_idUnique ultrasound identifier number.

◆ fsm_ultrasound_new()

fsm_ultrasound_t* fsm_ultrasound_new ( uint32_t  ultrasound_id)

Create a new ultrasound FSM.

This function creates a new ultrasound transceiver FSM with the given ultrasound ID.

Parameters
ultrasound_idUltrasound ID. Must be unique.
Returns
fsm_ultrasound_t* Pointer to the ultrasound FSM.

◆ fsm_ultrasound_set_state()

void fsm_ultrasound_set_state ( fsm_ultrasound_t p_fsm,
int8_t  state 
)

Set the state of the ultrasound FSM.

This function sets the current state of the ultrasound FSM.

    💡 This function is important because the struct is private and external functions such as those of the unit tests cannot access the state of the FSM directly.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
stateNew state of the ultrasound FSM.

◆ fsm_ultrasound_set_status()

void fsm_ultrasound_set_status ( fsm_ultrasound_t p_fsm,
bool  status 
)

Set the status of the ultrasound sensor. true means that the ultrasound sensor is active and a distance measurement must be performed. false means that the ultrasound sensor is inactive.

TODO alumnos:

✅ 1. Update the field status with the received value

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.
statusStatus of the ultrasound sensor.

◆ fsm_ultrasound_start()

void fsm_ultrasound_start ( fsm_ultrasound_t p_fsm)

Start the ultrasound sensor.

This function starts the ultrasound sensor by indicating to the port to start the ultrasound sensor (to reset all timer ticks) and to set the status of the ultrasound sensor to active.

TODO alumnos:

✅ 1. Set the field status.
✅ 2. Reset the field distance_idx.
✅ 3. Reset the field distance_cm.
✅ 4. Call function port_ultrasound_reset_echo_ticks() with the right parameters.
✅ 5. Call function port_ultrasound_set_trigger_ready() with the right parameters to indicate that the ultrasound sensor is ready to start a new measurement.
✅ 6. Call function port_ultrasound_start_new_measurement_timer() to force the new measurement timer to start to provoke the first interrupt.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.

◆ fsm_ultrasound_stop()

void fsm_ultrasound_stop ( fsm_ultrasound_t p_fsm)

Stop the ultrasound sensor.

This function stops the ultrasound sensor by indicating to the port to stop the ultrasound sensor (to reset all timer ticks) and to set the status of the ultrasound sensor to inactive.

TODO alumnos:

✅ 1. Reset the field status.
✅ 2. Call function port_ultrasound_stop_ultrasound() with the right parameters.

Parameters
p_fsmPointer to an fsm_ultrasound_t struct.

Variable Documentation

◆ fsm_trans_ultrasound

fsm_trans_t fsm_trans_ultrasound[]
static

Array representing the transitions table of the FSM ultrasound.

Warning
The order of the transitions is important. The FSM will check the transitions in the order they are defined in this array. In state SET_DISTANCE, the FSM will first check if a new measurement is ready (check_new_measurement()), then if the ultrasound sensor is off (check_off()). If the order is changed, the FSM may not work as expected and may finish measurements before time.
FSM_ULTRASOUND_NUM_MEASUREMENTS
#define FSM_ULTRASOUND_NUM_MEASUREMENTS
Definition: fsm_ultrasound.h:20
_compare
int _compare(const void *a, const void *b)
Compare function to sort arrays.
Definition: fsm_ultrasound.c:47