INF2004_Project/frtos/line_sensor/line_sensor.c

209 lines
4.7 KiB
C

#include "line_sensor.h"
#include "string.h"
const float conversionFactor = 3.3f / (1 << 12);
volatile u_int8_t map[MAP_SIZE][MAP_SIZE] = {0};
/**
* @brief Get the status of the Line Sensor
* @param gpio The GPIO pin to read from
* @return state_t LINE_DETECTED or LINE_NOT_DETECTED
*/
static inline state_t
get_state(uint gpio) {
adc_select_input(gpio - 26); // 26 is the first ADC pin (ADC0)
// ADC Conversion, vref is 3.3V, 12 bit resolution
float adc = (float) adc_read() * conversionFactor;
return (adc > THRESHOLD)
? LINE_DETECTED : LINE_NOT_DETECTED;
}
/**
* @brief Get the Direction based on the Line Sensor
*
* This function will detect if the line sensor is detecting a line or not
* It will read from both ADC channels and return if both are detecting a line
*
* @return state_t LINE_DETECTED or LINE_NOT_DETECTED
*/
static inline
direction_t get_current_dir() {
#ifdef ADC_PIN_TWO
state_t state_two = get_state(ADC_PIN_TWO);
#endif
state_t state_one = get_state(ADC_PIN_ONE);
#ifdef ADC_PIN_TWO
direction_t direction = (state_one << 1) | state_two;
#else
direction_t direction = state_one;
#endif
return direction;
}
/**
* @brief Setup the Line Sensor
*
* This function will setup the Line Sensor by initializing the ADC
*/
void
line_sensor_setup() {
adc_init();
adc_gpio_init(ADC_PIN_ONE);
#ifdef ADC_PIN_TWO
adc_gpio_init(ADC_PIN_TWO);
#endif
#ifdef ADC_PIN_THREE // Additional ADC Pin for Barcode Scanner
adc_gpio_init(ADC_PIN_THREE);
#endif
}
/**
* @brief Initialize the car's initial state
*
* @return The initialized car state
*/
car_state_t
initialize_car_state() {
car_state_t car_state;
car_state.x = MAP_SIZE >> 1;
car_state.y = MAP_SIZE >> 1;
car_state.current_direction = FORWARD;
car_state.orientation = NORTH;
map[car_state.x][car_state.y] = MAP_START_SYMBOL;
return car_state;
}
/**
* @brief Update the map based on the car's state
*
* @param car_state The current car state
*/
static inline void
update_map(car_state_t car_state) {
if (car_state.x >= 0 && car_state.x < MAP_SIZE &&
car_state.y >= 0 && car_state.y < MAP_SIZE) {
map[car_state.x][car_state.y] = 1;
}
}
/**
* @brief Handle forward movement of the car
*
* @param car_state The current car state
*/
static void
handle_forward_movement(car_state_t *car_state) {
printf("FORWARD, ");
// TODO: Check car's actual forward movement
switch (car_state->orientation) {
case NORTH:
printf("NORTH\n");
car_state->y++;
break;
case EAST:
printf("EAST\n");
car_state->x++;
break;
case SOUTH:
printf("SOUTH\n");
car_state->y--;
break;
case WEST:
printf("WEST\n");
car_state->x--;
break;
}
}
/**
* @brief Handle a right turn of the car
*
* Note: Bitwise AND with 0x03 to ensure that the orientation
* is always between 0 and 3
* @param car_state The current car state
*/
static inline void
handle_right_turn(car_state_t *car_state) {
car_state->orientation = (car_state->orientation + 1) & 0x03;
}
/**
* @brief Handle a left turn of the car
*
* @param car_state The current car state
*/
static inline void
handle_left_turn(car_state_t *car_state) {
car_state->orientation = (car_state->orientation - 1) & 0x03;
}
/**
* @brief Print the map to the console
*
* This function will print the map to the console
*/
void
print_map() {
// Invert the map, 0,0 is at the bottom left
for (int i = MAP_SIZE - 1; i >= 0; i --)
{
for (int j = 0; j < MAP_SIZE; j ++)
{
printf("%d ", map[j][i]);
}
printf("\n");
}
}
/**
* @brief FreeRTOS Task to read from the line sensor
*
* This task will read from the line sensor and print the state to the console
*
* @param params Pointer to the task parameters
*/
void
line_sensor_task(__unused void *params) {
car_state_t car_state = initialize_car_state();
sleep_ms(2000);
printf("Starting Line Sensor Task\n");
for (u_int8_t i = 40; i != 0; i--) {
car_state.current_direction = get_current_dir();
switch (car_state.current_direction) {
case FORWARD:
handle_forward_movement(&car_state);
break;
case RIGHT:
handle_right_turn(&car_state);
break;
case LEFT:
handle_left_turn(&car_state);
break;
default:
break;
}
update_map(car_state);
sleep_ms(ADC_READING_DELAY_MS);
}
print_map();
}