/**
* @file main.c
* @author Amar Kulovac
* @copyright SPDX-License-Identifier: MIT
* @brief Main module for the Raspberry Pi Pico noise-maker interface.
* This module interfaces with a noise-maker chip via ADC and reports the
* calculated voltage. It also outputs string data to an SPI display chip,
* using newline characters as delimiters.
*/
#include "hardware/adc.h"
#include "hardware/spi.h"
#include "pico/stdlib.h"
#include <stdio.h>
#include <string.h>
/** @name ADC Configuration */
/**@{*/
#define ADC_PIN 28 /**< GPIO pin used for ADC input */
#define ADC_PORT 2 /**< ADC MUX input index corresponding to GPIO 28 */
/**@}*/
/** @name SPI Configuration */
/**@{*/
#define TFT_SPI spi0 /**< Hardware SPI instance used for the display */
#define CS_PIN 27 /**< Chip Select (nCS) GPIO pin */
#define SCK_PIN 18 /**< SPI Serial Clock GPIO pin */
#define MOSI_PIN 19 /**< SPI Main-Out-Sub-In GPIO pin */
#define SCK_FREQ 1000000 /**< SPI Clock Frequency (1MHz) */
/**@}*/
/** @brief Main loop delay in milliseconds */
#define SLEEP 1000
/**
* @brief ADC scaling factor.
* @note Testing indicates the Wokwi simulation environment uses a 5.0V
* reference for its analog engine, resulting in values bounded between 0 and 1.
* On physical hardware, this would typically be 3.3f.
*/
const float conversion_factor = 5.0f / ((1 << 12) - 1);
/**
* @brief Converts raw ADC integer values to a floating-point voltage.
* @param raw The 12-bit digital value read from the ADC (0-4095).
* @return float The calculated voltage based on the conversion_factor.
*/
float raw_to_voltage(uint16_t raw) { return (float)raw * conversion_factor; }
/**
* @brief Application entry point.
* * Initializes standard I/O, configures the ADC for noise-maker input,
* and sets up the SPI peripheral for the TFT display. The main loop
* continuously reads the ADC and transmits the formatted string via SPI.
*/
int main() {
stdio_init_all();
/* ADC Initialization */
adc_init();
adc_gpio_init(ADC_PIN);
adc_select_input(ADC_PORT);
/* SPI Initialization */
spi_init(TFT_SPI, SCK_FREQ);
gpio_set_function(SCK_PIN, GPIO_FUNC_SPI);
gpio_set_function(MOSI_PIN, GPIO_FUNC_SPI);
/* Chip Select (nCS) Setup */
gpio_init(CS_PIN);
gpio_set_dir(CS_PIN, GPIO_OUT);
gpio_put(CS_PIN, 1);
printf("pico initialized\n");
while (true) {
uint16_t raw_value = adc_read();
float voltage = raw_to_voltage(raw_value);
printf("Raw: %d, Voltage: %f V\n", raw_value, voltage);
char buffer[16];
snprintf(buffer, sizeof(buffer), "%.3f", voltage);
/* Assert nCS Low to start communication */
gpio_put(CS_PIN, 0);
spi_write_blocking(TFT_SPI, "Voltage: ", 9);
spi_write_blocking(TFT_SPI, buffer, strlen(buffer));
spi_write_blocking(TFT_SPI, "V\n", 2);
/* Assert nCS High to end communication */
gpio_put(CS_PIN, 1);
/* Data sent while CS is High will be ignored by the peripheral */
spi_write_blocking(TFT_SPI, "wont appear\n", 12);
sleep_ms(SLEEP);
}
}