diff --git a/inc/RegEdit.h b/inc/RegEdit.h new file mode 100644 index 0000000..4956b42 --- /dev/null +++ b/inc/RegEdit.h @@ -0,0 +1,71 @@ +/** + * @brief Module/Interface for editing AVR registers + * @details This file is an interface to AVR registers or the avr/io.h + * @author Jake G + * @date 2024 + * @copyright None + * @file RegEdit.h + */ + +#ifndef REGEDIT_H +#define REGEDIT_H + +#include +#include + + +/** + * @brief Sets the value of the register to 0xFF. + * @param reg A pointer to a register + */ +void RegEdit_SetRegister(void *reg); + +/** + * @brief Sets the value of the register to 0x00. + * @param reg A pointer to a register + */ +void RegEdit_ClearRegister(void *reg); + +/** + * @brief Sets a single bit in the register. + * @param reg A pointer to a register + * @param The bit's index or number in the register + */ +void RegEdit_SetBit(void *reg, uint8_t bit_num); + +/** + * @brief Clears a single bit in the register. + * @param reg A pointer to a register + * @param The bit's index or number in the register + */ +void RegEdit_ClearBit(void *reg, uint8_t bit_num); + +/** + * @brief Checks if a single bit is set in the register. + * @param reg A pointer to a register + * @param The bit's index or number in the register + */ +bool RegEdit_IsBitSet(void *reg, uint8_t bit_num); + +/** + * @brief Preforms logical OR Equals with the passed num. + * @param reg A pointer to a register + * @param The bit's index or number in the register + */ +void RegEdit_OR_Num(void *reg, uint8_t num); + +/** + * @brief Preforms logical AND Equals with the passed num. + * @param reg A pointer to a register + * @param The bit's index or number in the register + */ +void RegEdit_AND_Num(void *reg, uint8_t num); + +/** + * @brief Sets the register to the passed number value. + * @param reg A pointer to a register + * @param The bit's index or number in the register + */ +void RegEdit_SetNum(void *reg, uint8_t num); + +#endif //REGEDIT_H diff --git a/inc/config.h b/inc/config.h new file mode 100644 index 0000000..8e9d2c0 --- /dev/null +++ b/inc/config.h @@ -0,0 +1,60 @@ +/** + * @file config.h + * @author Jake G + * @date 15 June 2024 + * @brief File contains the project configuration values + * + * This file contains the user changable parameters. Most the values are + * constants that will change the behavior of the system. + * + * For these changes to take affect you must recompile/rebuild the project + * after you have changed the values. + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#include + +#define ADC_LOAD1 4 +#define ADC_LOAD2 5 +#define ADC_LOAD3 6 + +/** + * @brief Positive Zero Crossing Trigger Value + * The 10 bit value at which the program triggers the ISR to handle + * the zero crossing event. + * + * You can adjust this to change when the program will start the timer. + */ +const uint16_t TriggerValue = 512; + + +/** + * @brief Triac Gate Pulse Quantity + * + * Contains the number of pulses that the micro-controller will send to the + * gates of the triac. + * + * This number should match the quantity of timings inside the pulse/duration + * array. + */ +const int GatePulsesQty = 5; + +/** + * @brief Gate Pulses Array + * + * The gate pulses array holds the duration of pulses in microseconds for the + * triacs gates. The length of the array must be matched with the + * GatePulsesQuantity parameter. + */ +const uint16_t GatePulses[5] = {250, 500, 750, 1000, 1250}; + +/** + * @brief The time constant. + */ +const double Tau = 8250; + + + +#endif //CONFIG_H diff --git a/src/ADC/ADC.c b/src/ADC/ADC.c new file mode 100644 index 0000000..e9329e8 --- /dev/null +++ b/src/ADC/ADC.c @@ -0,0 +1,99 @@ +/* + * Author: username + * Date: 2024 + * filename: ADC.c + * description: module_purpose + */ + +#ifndef __AVR_ATtiny404__ +#define __AVR_ATtiny404__ +#endif + +#include "ADC.h" +#include "RegEdit.h" +#include "avr/io.h" + +#define MAX_PIN_NUM 7 + +static bool IsInvalidPin(uint8_t pin_num) { + if (pin_num > MAX_PIN_NUM) { + return true; + } + return false; +} + +void ADC_Setup(void) { + // Clears control register A for ADC0 + RegEdit_SetNum((void *)&ADC0.CTRLA, 0x00); + + // Sets The sample accumulation number to 32. + RegEdit_SetNum((void *)&ADC0.CTRLB, 0x5); + + // Sets the voltage reference to VDD or VCC. + RegEdit_SetBit((void *)&ADC0.CTRLC, 4); + + // Sets the pre-scalar for the adc sample rate. + RegEdit_SetBit((void *)&ADC0.CTRLC, 2); + + // Setup an Initalization delay. + RegEdit_OR_Num((void *)&ADC0.CTRLD, (2 << 5)); + + // Set the bit for ADC variation during readings. + RegEdit_SetBit((void *)&ADC0.CTRLD, 4); +} + +void ADC_Init(uint8_t pin_num) { + + if (IsInvalidPin(pin_num)) { + return; + } + + // set the direction to input + RegEdit_ClearBit((void *)&PORTA.DIR, pin_num); + + // Disable the pull-up resistor + RegEdit_ClearBit((void *)&PORTA.OUT, pin_num); + + // Disable input buffer + // We do some kinda nasty address addition but it saves + // memory and means we don't need a switch statment. + RegEdit_SetBit((void *)(&PORTA.PIN0CTRL) + pin_num, + PORT_ISC_INPUT_DISABLE_gc); +} + +void ADC_Enable(void) { + // Set the enable bit in the CTRLA register + RegEdit_SetBit((void *)&ADC0.CTRLA, 0); +} + +void ADC_Disable() { + // Clear the enable ADC flag + RegEdit_ClearBit((void *)&ADC0.CTRLA, 0); +} + +void ADC_SetPin(uint8_t pin_num) { + if (IsInvalidPin(pin_num)) { + return; + } + RegEdit_ClearRegister((void *)&ADC0.MUXPOS); + RegEdit_SetNum((void *)&ADC0.MUXPOS, pin_num); +} + +uint16_t ADC_ReadValue_Impl(uint8_t pin_num) { + RegEdit_SetNum((void *)&ADC0.COMMAND, ADC_STCONV_bm); + + /* Wait until ADC conversion done */ + while (!(ADC0.INTFLAGS & ADC_RESRDY_bm)) { + ; + } + + /* Clear the interrupt flag by writing 1: */ + ADC0.INTFLAGS = ADC_RESRDY_bm; + + uint16_t adc_val = (uint16_t)ADC0.RES; + adc_val = adc_val >> 5; + return adc_val; +} + +// Set the default for the function pointer. +uint16_t (*ADC_ReadValue)(uint8_t pin_num) = ADC_ReadValue_Impl; diff --git a/src/ADC/ADC.h b/src/ADC/ADC.h new file mode 100644 index 0000000..896c8ff --- /dev/null +++ b/src/ADC/ADC.h @@ -0,0 +1,68 @@ +/** + * @brief Interface to the AVR ADC hardware. + * @details This file is... + * @author Jake G + * @date 2024 + * @copyright None + * @file ADC.h + */ + +#ifndef ADC_H +#define ADC_H + +#include +#include + +/** + * @brief Initializes the AVR hardware in order to accept + * Input for ADC usage. + * @param pin_num The number of the pin 0-7 you are initializing. + * + * This function only makes use of PORTA by default. It sets the direction + * register to input, disables the pull-up resistor and also diables interrupts + * alongside the input buffer(digital). + * + * This in turn helps reduce noise when using the ADC. + * + */ +void ADC_Init(uint8_t pin_num); + +/** + * @brief Enables the ADC + */ +void ADC_Enable(void); + +/** + * @brief Disables the ADC + */ +void ADC_Disable(); + +/** + * @brief Reads ADC value into variable + * + * @param pin_num The bin number of the ADC pin being read. + * + * This function depends on the ADC already being initialized and enabled + * before being called. + */ +extern uint16_t (*ADC_ReadValue)(uint8_t pin_num); + +/** + * @brief Sets up the ADC + * + * This function sets up the ADC to take and accumulate 32 samples. It also + * sets the inital delay to 32 ADC clock cycles, and sets the VREF to VDD or + * VCC. + * + * This function should only need to be called once. + */ +void ADC_Setup(void); + +/** + * @brief Sets the pin used in the MUX for ADC0. + * + * @param pin_num The number of the pin in Port A. + */ +void ADC_SetPin(uint8_t pin_num); + +#endif // ADC_H diff --git a/src/ADC/CMakeLists.txt b/src/ADC/CMakeLists.txt new file mode 100644 index 0000000..3b39d8c --- /dev/null +++ b/src/ADC/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(ADC STATIC + ADC.c +) +target_include_directories(ADC PUBLIC + ${CMAKE_CURRENT_LIST_DIR} +) + +if(UNIT_TESTING) + target_link_libraries(ADC + MockRegEdit + ) + +else() + target_link_libraries(ADC + RegEdit + ) +endif() diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d5581e8..6c6fc5b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,11 @@ add_executable(${PROJECT_NAME} main.c ) +target_link_libraries(${PROJECT_NAME} + RegEdit + timer +) + # Ensure the build rules are defined set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf") @@ -38,3 +43,10 @@ add_custom_target(upload ALL DEPENDS hex ) endif() + + +add_subdirectory(RegEdit) +add_subdirectory(timer) +add_subdirectory(SuperLoop) +add_subdirectory(ADC) +add_subdirectory(load) diff --git a/src/RegEdit/CMakeLists.txt b/src/RegEdit/CMakeLists.txt new file mode 100644 index 0000000..8baf7a3 --- /dev/null +++ b/src/RegEdit/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(RegEdit STATIC + RegEdit.c +) + +target_include_directories(RegEdit PUBLIC + ${CMAKE_CURRENT_LIST_DIR} +) diff --git a/src/RegEdit/RegEdit.c b/src/RegEdit/RegEdit.c new file mode 100644 index 0000000..5087904 --- /dev/null +++ b/src/RegEdit/RegEdit.c @@ -0,0 +1,53 @@ +/* + * Author: username + * Date: 2024 + * filename: RegEdit.c + * description: module_purpose + */ + +#include "RegEdit.h" + +void RegEdit_SetRegister(void *reg) { + uint8_t *reg_ptr = (uint8_t *)reg; + *reg_ptr = 0xFF; +} + +void RegEdit_ClearRegister(void *reg) { + uint8_t *reg_ptr = (uint8_t *)reg; + *reg_ptr = 0x00; +} + +void RegEdit_SetBit(void *reg, uint8_t bit_num) { + uint8_t *reg_ptr = (uint8_t *)reg; + *reg_ptr |= (uint8_t)(1 << bit_num); +} + +void RegEdit_ClearBit(void *reg, uint8_t bit_num) { + uint8_t *reg_ptr = (uint8_t *)reg; + *reg_ptr &= ~(1 << bit_num); +} + +bool RegEdit_IsBitSet(void *reg, uint8_t bit_num) { + uint8_t *reg_ptr = (uint8_t *)reg; + return *reg_ptr & (1 << bit_num); +} + +void RegEdit_OR_Num(void *reg, uint8_t num) { + uint8_t *reg_ptr = (uint8_t *)reg; + *reg_ptr |= num; +} + +void RegEdit_AND_Num(void *reg, uint8_t num) { + uint8_t *reg_ptr = (uint8_t *)reg; + *reg_ptr &= num; +} + +void RegEdit_SetNum(void *reg, uint8_t num) { + uint8_t *reg_ptr = (uint8_t *)reg; + *reg_ptr = num; +} + +uint8_t RegEdit_ReadReg(void *reg) { + uint8_t *reg_ptr = (uint8_t *)reg; + return *reg_ptr; +} diff --git a/src/RegEdit/RegEdit.h b/src/RegEdit/RegEdit.h new file mode 100644 index 0000000..8ad2e91 --- /dev/null +++ b/src/RegEdit/RegEdit.h @@ -0,0 +1,77 @@ +/** + * @brief Register Editing Interface + * @details This file is an abstraction to all the bitwise operations + * @author Jake G + * @date 2024 + * @copyright None + * @file MockRegEdit.h + */ + +#ifndef REGEDIT_H +#define REGEDIT_H + +#include +#include + +/** + * + * @param reg The register address. + */ +void RegEdit_SetRegister(void *reg); + +/** + * + * @param reg The register address. + */ +void RegEdit_ClearRegister(void *reg); + +/** + * + * @param reg The register address. + * @param bit_num The bit location. + */ +void RegEdit_SetBit(void *reg, uint8_t bit_num); + +/** + * + * @param reg The register address. + * @param bit_num The bit location. + */ +void RegEdit_ClearBit(void *reg, uint8_t bit_num); + +/** + * + * @param reg The register address. + * @param bit_num The bit location. + * @return + */ +bool RegEdit_IsBitSet(void *reg, uint8_t bit_num); + +/** + * + * @param reg The register address. + * @param num The bit location. + */ +void RegEdit_OR_Num(void *reg, uint8_t num); + +/** + * + * @param reg The register address. + * @param num The bit location. + */ +void RegEdit_AND_Num(void *reg, uint8_t num); + +/** + * + * @param reg The register address. + * @param num The bit location. + */ +void RegEdit_SetNum(void *reg, uint8_t num); + +/** + * + * @param reg The register address. + */ +uint8_t RegEdit_ReadReg(void *reg); + +#endif // REGEDIT_H diff --git a/src/SuperLoop/CMakeLists.txt b/src/SuperLoop/CMakeLists.txt new file mode 100644 index 0000000..9275283 --- /dev/null +++ b/src/SuperLoop/CMakeLists.txt @@ -0,0 +1,7 @@ +add_library(SuperLoop STATIC + SuperLoop.c +) + +target_include_directories(SuperLoop PUBLIC + ${CMAKE_CURRENT_LIST_DIR} +) diff --git a/src/SuperLoop/SuperLoop.c b/src/SuperLoop/SuperLoop.c new file mode 100644 index 0000000..f14dc8b --- /dev/null +++ b/src/SuperLoop/SuperLoop.c @@ -0,0 +1,40 @@ +/* + * Author: Jake G + * Date: 2024-09-01 + * filename: SuperLoop.c + * description: The RT super loop. + */ + +#include "SuperLoop.h" +#include + +static uint8_t iteration_target = 0; + +/* + * #################################### + * PRIVATE FUNCTIONS + * #################################### + */ + +static bool continue_looping(uint8_t idx) { + if (iteration_target == 0 || idx <= iteration_target) { + return true; + } + return false; +} + +/* + * #################################### + * PUBLIC FUNCTIONS + * #################################### + */ + +void SuperLoop_SetIterations(uint8_t n) { iteration_target = n; } + +uint8_t SuperLoop_Run(void) { + uint8_t i; + for (i = 0; continue_looping(i); i++) { + continue; + } + return i - 1; +} diff --git a/src/SuperLoop/SuperLoop.h b/src/SuperLoop/SuperLoop.h new file mode 100644 index 0000000..4489135 --- /dev/null +++ b/src/SuperLoop/SuperLoop.h @@ -0,0 +1,29 @@ +/** + * @brief The Systems superloop that handles all the tasks. + * @details This file is the main program's logic that loops endlessly + * @author Jake G + * @date 2024-09-01 + * @copyright None + * @file SUPERLOOP.h + */ + +#ifndef SUPERLOOP +#define SUPERLOOP + +#include + +/** + * A function that allows the user to set the number of loop iterations for + * testing purposes. + * @param n The number of times it will loop before breaking. (Zero is endless) + */ +void SuperLoop_SetIterations(uint8_t n); + +/** + * The super loop; it runs the main code in a loop endlessly unless the number + * of iterations are set. + * @return The number of loops completed in iteration mode. + */ +uint8_t SuperLoop_Run(void); + +#endif // SUPERLOOP diff --git a/src/timer/CMakeLists.txt b/src/timer/CMakeLists.txt new file mode 100644 index 0000000..b6c0bb7 --- /dev/null +++ b/src/timer/CMakeLists.txt @@ -0,0 +1,17 @@ +add_library(timer STATIC + timer.c +) + +target_include_directories(timer PUBLIC + ${CMAKE_CURRENT_LIST_DIR} +) + +if(UNIT_TESTING) + target_link_libraries(timer + MockRegEdit + ) +else() + target_link_libraries(timer + RegEdit + ) +endif() diff --git a/src/timer/timer.c b/src/timer/timer.c new file mode 100644 index 0000000..700d6c7 --- /dev/null +++ b/src/timer/timer.c @@ -0,0 +1,75 @@ +/** + * @brief PUT_TEXT_HERE + * @details This file is... + * @author username + * @date todays_date + * @copyright None + * @file module_name.h + */ + +// Used during testing and for the LSP +#ifndef __AVR_ATtiny404__ +#define __AVR_ATtiny404__ +#endif + +#include "timer.h" +#include +#include + +#define FCLK_PER 3333333UL +#define DIV8 0x3 +#define PERIOD_VALUE 40 + +// These are expiremential found values that account for overhead +// for smaller durations. +#define OVERHEAD_ONE 226 +#define OVERHEAD_TWO 151 +#define OVERHEAD_THREE 75 + +static uint16_t overflow_count = 0; + +uint16_t Timer_GetOverflowCount(void) { return overflow_count; } + +void Timer_Start(void) { + // clear the overflow event count + overflow_count = 0; + + sei(); + + // Enable the overflow Interrupt. + TCA0.SINGLE.INTCTRL = TCA_SINGLE_OVF_bm; + + // set Normal mode. + TCA0.SINGLE.CTRLB = TCA_SINGLE_WGMODE_NORMAL_gc; + + // Disable event counting. + TCA0.SINGLE.EVCTRL &= ~(TCA_SINGLE_CNTEI_bm); + + // Set the Period Value + TCA0.SINGLE.PER = PERIOD_VALUE; + + // set the Timer to divide FCLK_PER by 8. + TCA0.SINGLE.CTRLA |= (DIV8 << 1); + + // Enable the Timer + TCA0.SINGLE.CTRLA |= TCA_SINGLE_ENABLE_bm; +} + +void Timer_Disable(void) { + cli(); + TCA0.SINGLE.CTRLA &= ~(1 << 0); + TCA0.SINGLE.CTRLESET |= ((0x3) << 2); +} + +// Triggered on the overflow of the timer A's counter. +ISR(TCA0_OVF_vect) { + cli(); + + // Increment the Overflow counter. + overflow_count += 1; + + // The interrupt flag has to be cleared manually + TCA0.SINGLE.INTFLAGS = TCA_SINGLE_OVF_bm; + + sei(); +} diff --git a/src/timer/timer.h b/src/timer/timer.h new file mode 100644 index 0000000..833712b --- /dev/null +++ b/src/timer/timer.h @@ -0,0 +1,32 @@ +/** + * @brief The AVR Timer module + * @details This file is used to interact with the hardware timers. + * @author Jake G + * @date 2024 + * @copyright None + * @file TIMER.h + */ + +#ifndef TIMER +#define TIMER + +#include "inttypes.h" +#include "stdbool.h" + +/** + * Starts up the AVR timer using a 10KHz frequency + */ +void Timer_Start(void); + +/** + * Stops the AVR timer. + */ +void Timer_Stop(void); + +/** + * Get the number of times the timer's counter setup for 10kHz overflowed. + * @return A uint16_t holding the number of counter overflow events. + */ +uint16_t Timer_GetOverflowCount(void); + +#endif // TIMER diff --git a/tests/ADC/CMakeLists.txt b/tests/ADC/CMakeLists.txt new file mode 100644 index 0000000..6318a53 --- /dev/null +++ b/tests/ADC/CMakeLists.txt @@ -0,0 +1,17 @@ +# TEST_RUNNER +add_library(test_ADC + test_ADC.cpp +) + +target_link_libraries(test_ADC + ${CPPUTEST_LIBRARIES}/libCppUTest.a + ${CPPUTEST_LIBRARIES}/libCppUTestExt.a + ADC + MockRegEdit +) + +#Needed for the tests to function +include_directories( + /usr/local/avr/include/avr + #/usr/lib/avr/include/avr +) diff --git a/tests/ADC/test_ADC.cpp b/tests/ADC/test_ADC.cpp new file mode 100644 index 0000000..b9abb6a --- /dev/null +++ b/tests/ADC/test_ADC.cpp @@ -0,0 +1,192 @@ +/* + * Author: Jake G + * Date: 2024 + * filename: test_ADC.c + * description: module_purpose + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTestExt/MockSupport.h" +#include + +//This define allows us to dircetly include the device header without error. +#define _AVR_IO_H_ + + +extern "C" +{ +#include //ATtiny404 header fille. +#include "ADC.h" +} + +TEST_GROUP(test_ADC) +{ + void setup() + { + + } + void teardown() + { + mock().checkExpectations(); + mock().clear(); + } +}; + +TEST(test_ADC, FirstTest) +{ + CHECK(true); +} + + +TEST(test_ADC, ADC_SetupSetsRegisters) +{ + //Clears control register A for ADC0 + mock().expectOneCall("RegEdit_SetNum") + .withPointerParameter("reg", (void *) &ADC0.CTRLA) + .withUnsignedIntParameter("num", 0x00); + + //Sets The sample accumulation number to 32. + mock().expectOneCall("RegEdit_SetNum") + .withPointerParameter("reg", (void *) &ADC0.CTRLB) + .withUnsignedIntParameter("num", 0x5); + + //Sets the voltage reference to VDD or VCC. + mock().expectOneCall("RegEdit_SetBit") + .withPointerParameter("reg", (void *) &ADC0.CTRLC) + .withUnsignedIntParameter("bit_num", 4); + + //Sets the pre-scalar for the adc sample rate. + mock().expectOneCall("RegEdit_SetBit") + .withPointerParameter("reg", (void *) &ADC0.CTRLC) + .withUnsignedIntParameter("bit_num", 2); + + //Setup an Initalization delay. + mock().expectOneCall("RegEdit_OR_Num") + .withPointerParameter("reg", (void *) &ADC0.CTRLD) + .withUnsignedIntParameter("num", (2<<5)); + + //Set the bit for ADC variation during readings. + mock().expectOneCall("RegEdit_SetBit") + .withPointerParameter("reg", (void *) &ADC0.CTRLD) + .withUnsignedIntParameter("bit_num", 4); + + ADC_Setup(); +} + +TEST(test_ADC, ADC_InitPortAPin7UsesCorrectRegisters) +{ + //Check for setting the direction to input. + mock().expectOneCall("RegEdit_ClearBit") + .withPointerParameter("reg", (void *) &PORTA.DIR) + .withUnsignedIntParameter("bit_num", 7); + + //Check that the pullup is off + mock().expectOneCall("RegEdit_ClearBit") + .withPointerParameter("reg", (void *) &PORTA.OUT) + .withUnsignedIntParameter("bit_num", 7); + + //Set the ISC(input sense config) to disable digital input + //buffering and reduce the noise on ADC usage. + mock().expectOneCall("RegEdit_SetBit") + .withPointerParameter("reg", (void *) &PORTA.PIN7CTRL) + .withUnsignedIntParameter("bit_num", PORT_ISC_INPUT_DISABLE_gc); + + + ADC_Init(7); +} + +TEST(test_ADC, ADC_InitPortAPin0UsesCorrectRegisters) +{ + + //Check for setting the direction to input. + mock().expectOneCall("RegEdit_ClearBit") + .withPointerParameter("reg", (void *) &PORTA.DIR) + .withUnsignedIntParameter("bit_num", 0); + + //Check that the pullup is off + mock().expectOneCall("RegEdit_ClearBit") + .withPointerParameter("reg", (void *) &PORTA.OUT) + .withUnsignedIntParameter("bit_num", 0); + + //Set the ISC(input sense config) to disable digital input + //buffering and reduce the noise on ADC usage. + mock().expectOneCall("RegEdit_SetBit") + .withPointerParameter("reg", (void *) &PORTA.PIN0CTRL) + .withUnsignedIntParameter("bit_num", PORT_ISC_INPUT_DISABLE_gc); + + + ADC_Init(0); +} + +TEST(test_ADC, ADC_InitDoesNothingOnHighPinNumbers) +{ + mock().expectNoCall("RegEdit_SetBit"); + ADC_Init(8); +} + +TEST(test_ADC, ADC_EnablePasses) +{ + + mock().expectOneCall("RegEdit_SetBit") + .withPointerParameter("reg", (void *) &ADC0.CTRLA) + .withUnsignedIntParameter("bit_num", 0); + + ADC_Enable(); + +} + +TEST(test_ADC, ADC_DisablePasses) +{ + mock().expectOneCall("RegEdit_ClearBit") + .withPointerParameter("reg", (void *) &ADC0.CTRLA) + .withUnsignedIntParameter("bit_num", 0); + + ADC_Disable(); +} + +TEST(test_ADC, ADC_SetPinSetsRightRegisters) +{ + //It clears existing MUXPOS register values. + mock().expectOneCall("RegEdit_ClearRegister") + .withPointerParameter("reg", (void *) &ADC0.MUXPOS); + + //It Correctly sets the pin number. + mock().expectOneCall("RegEdit_SetNum") + .withPointerParameter("reg", (void *) &ADC0.MUXPOS) + .withUnsignedIntParameter("num", 4); + + ADC_SetPin(4); +} + + +TEST(test_ADC, ADC_SetPinFailsOnInvalidPin) +{ + ADC_SetPin(8); +} + + +static uint16_t ADC_ReadValueFake(uint8_t pin_num) +{ + return 512; +} + +TEST_GROUP(test_ADCRead) +{ + void setup() + { + UT_PTR_SET(ADC_ReadValue, ADC_ReadValueFake); + } + + void teardown() + { + + } +}; + +TEST(test_ADCRead, FunctionPointerSwapWorks) +{ + uint16_t value = ADC_ReadValue(0); + + LONGS_EQUAL(512, value); +} + diff --git a/tests/AllTests.cpp b/tests/AllTests.cpp index 24024d0..ea7ed89 100644 --- a/tests/AllTests.cpp +++ b/tests/AllTests.cpp @@ -3,6 +3,10 @@ //ImportTestGroups IMPORT_TEST_GROUP(simple_test); +IMPORT_TEST_GROUP(test_SuperLoop); +IMPORT_TEST_GROUP(test_ADC); +IMPORT_TEST_GROUP(test_RegEdit); + //START: main int main(int argc, char** argv) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7bcd8ee..8429519 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,13 @@ project(Tests) # TEST_DIRS +add_subdirectory(SuperLoop) +add_subdirectory(ADC) +add_subdirectory(MockADC) +add_subdirectory(RegEdit) +add_subdirectory(MockRegEdit) add_subdirectory(simple_test) +#add_subdirectory(timer) # TEST_RUNNER add_executable(AllTests @@ -12,5 +18,19 @@ target_link_libraries(AllTests ${CPPUTEST_LIBRARIES}/libCppUTest.a ${CPPUTEST_LIBRARIES}/libCppUTestExt.a # TEST_LINKS + test_SuperLoop + test_ADC + test_RegEdit simple_test ) + +add_executable(Mock_Tests + MockTests.cpp +) + +target_link_libraries(Mock_Tests + ${CPPUTEST_LIBRARIES}/libCppUTest.a + ${CPPUTEST_LIBRARIES}/libCppUTestExt.a + test_MockRegEdit + test_MockADC +) diff --git a/tests/MockADC/CMakeLists.txt b/tests/MockADC/CMakeLists.txt new file mode 100644 index 0000000..cd51613 --- /dev/null +++ b/tests/MockADC/CMakeLists.txt @@ -0,0 +1,10 @@ +# TEST_RUNNER +add_library(test_MockADC + test_MockADC.cpp +) + +target_link_libraries(test_MockADC + ${CPPUTEST_LIBRARIES}/libCppUTest.a + ${CPPUTEST_LIBRARIES}/libCppUTestExt.a + MockADC +) diff --git a/tests/MockADC/test_MockADC.cpp b/tests/MockADC/test_MockADC.cpp new file mode 100644 index 0000000..8b0b5ee --- /dev/null +++ b/tests/MockADC/test_MockADC.cpp @@ -0,0 +1,94 @@ +/* + * Author: Jake G + * Date: 2024 + * filename: test_MockADC.c + * description: + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTestExt/MockSupport.h" +#include + +extern "C" +{ +#include "MockADC.h" +} + +TEST_GROUP(test_MockADC) +{ + void setup() + { + + } + void teardown() + { + mock().checkExpectations(); + mock().clear(); + } +}; + +TEST(test_MockADC, ADC_InitExpects) +{ + mock().expectOneCall("ADC_Init") + .withUnsignedIntParameter("pin_num", 7); + + ADC_Init(7); +} + +TEST(test_MockADC, ADC_EnableExpects) +{ + mock().expectOneCall("ADC_Enable"); + + ADC_Enable(); +} + + +TEST(test_MockADC, ADC_DisableExpect) +{ + mock().expectOneCall("ADC_Disable"); + + ADC_Disable(); +} + +TEST(test_MockADC, ADC_ReadValue) +{ + MockADC_ZeroIndex(); + MockADC_PushValue(512); + + mock().expectOneCall("ADC_ReadValue_Impl") + .withUnsignedIntParameter("pin_num", 0x2); + + uint16_t val = ADC_ReadValue(0x2); + LONGS_EQUAL(512, val); + +} + +TEST(test_MockADC, ADC_ReadValueReturnsZeroOnEmptyBuffer) +{ + MockADC_ZeroIndex(); + + mock().expectOneCall("ADC_ReadValue_Impl") + .withUnsignedIntParameter("pin_num", 0x2) + .andReturnValue(0x0000); + + uint16_t val = ADC_ReadValue(0x2); + LONGS_EQUAL(0, val); +} + +TEST(test_MockADC, MockADC_PushValueDoesntOverflowArray) +{ + MockADC_ZeroIndex(); + for(int i = 0; i < 257; i++){ + MockADC_PushValue(512+i); + CHECK_TRUE(MockADC_GetIndex() <= 255); + } +} + +TEST(test_MockADC, MockADC_SetupSetsGlobal) +{ + CHECK_FALSE(MockADC_IsSetup()); + + ADC_Setup(); + + CHECK_TRUE(MockADC_IsSetup()); +} diff --git a/tests/MockRegEdit/CMakeLists.txt b/tests/MockRegEdit/CMakeLists.txt new file mode 100644 index 0000000..f1a8ab3 --- /dev/null +++ b/tests/MockRegEdit/CMakeLists.txt @@ -0,0 +1,11 @@ +# TEST_RUNNER +add_library(test_MockRegEdit + test_MockRegEdit.cpp +) + +target_link_libraries(test_MockRegEdit + ${CPPUTEST_LIBRARIES}/libCppUTest.a + ${CPPUTEST_LIBRARIES}/libCppUTestExt.a + MockRegEdit +) + diff --git a/tests/MockRegEdit/test_MockRegEdit.cpp b/tests/MockRegEdit/test_MockRegEdit.cpp new file mode 100644 index 0000000..49db643 --- /dev/null +++ b/tests/MockRegEdit/test_MockRegEdit.cpp @@ -0,0 +1,168 @@ +/* + * Author: username + * Date: todays_date + * filename: test_MockRegEdit.c + * description: module_purpose + */ + +#include "CppUTest/CommandLineTestRunner.h" +#include "CppUTestExt/MockSupport.h" +#include + +extern "C" +{ +#include "MockRegEdit.h" +} + + + + +TEST_GROUP(test_MockRegEdit) +{ + void setup() + { + } + void teardown() + { + mock().clear(); + } +}; + + +TEST(test_MockRegEdit, RegEdit_ClearRegisterExpectedCallPasses) +{ + uint8_t a; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_ClearRegister") + .withPointerParameter("reg", b); + + RegEdit_ClearRegister(b); + + mock().checkExpectations(); +} + + +TEST(test_MockRegEdit, RegEdit_SetRegisterExpectedCallPasses) +{ + + uint8_t a; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_SetRegister") + .withPointerParameter("reg", b); + + RegEdit_SetRegister(b); + + mock().checkExpectations(); +} + + +TEST(test_MockRegEdit, RegEdit_SetBitExpectedCallPasses) +{ + + uint8_t a; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_SetBit") + .withPointerParameter("reg", b) + .withUnsignedIntParameter("bit_num", 5); + + RegEdit_SetBit(b, 5); + + mock().checkExpectations(); +} + + +TEST(test_MockRegEdit, RegEdit_ClearBitExpectedCallPasses) +{ + + uint8_t a; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_ClearBit") + .withPointerParameter("reg", b) + .withUnsignedIntParameter("bit_num", 5); + + RegEdit_ClearBit(b, 5); + + mock().checkExpectations(); +} + +TEST(test_MockRegEdit, RegEdit_IsBitSetExpectedCallPasses) +{ + uint8_t a = 0xFF; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_IsBitSet") + .withPointerParameter("reg", b) + .withUnsignedIntParameter("bit_num", 5) + .andReturnValue(true); + + CHECK_TRUE(RegEdit_IsBitSet(b, 5)); + + mock().checkExpectations(); +} + + +TEST(test_MockRegEdit, RegEdit_IsBitSetExpectedCallPassesWithFalse) +{ + uint8_t a = 0xFF; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_IsBitSet") + .withPointerParameter("reg", b) + .withUnsignedIntParameter("bit_num", 5) + .andReturnValue(false); + + CHECK_FALSE(RegEdit_IsBitSet(b, 5)); + + mock().checkExpectations(); +} + +TEST(test_MockRegEdit, RegEdit_OR_NumExpectedWorks) +{ + uint8_t a = 0xFF; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_OR_Num") + .withPointerParameter("reg", b) + .withUnsignedIntParameter("num", 0x4) + .andReturnValue(false); + + RegEdit_OR_Num(b, 0x4); + + mock().checkExpectations(); + + +} + +TEST(test_MockRegEdit, RegEdit_SetNumPasses) +{ + uint8_t a = 0xFF; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_SetNum") + .withPointerParameter("reg", b) + .withUnsignedIntParameter("num", 0x4) + .andReturnValue(false); + + RegEdit_SetNum(b, 0x4); + + mock().checkExpectations(); +} + +TEST(test_MockRegEdit, RegEdit_ReadRegPasses) +{ + uint8_t a = 0xFF; + uint8_t *b = &a; + + mock().expectOneCall("RegEdit_ReadReg") + .withPointerParameter("reg", b) + .andReturnValue(0xFF); + + uint8_t reg_val = RegEdit_ReadReg(b); + LONGS_EQUAL(0xFF, reg_val); + + mock().checkExpectations(); +} diff --git a/tests/MockTests.cpp b/tests/MockTests.cpp new file mode 100644 index 0000000..a91591f --- /dev/null +++ b/tests/MockTests.cpp @@ -0,0 +1,13 @@ +#include "CppUTest/CommandLineTestRunner.h" + + +//ImportTestGroups +IMPORT_TEST_GROUP(test_MockRegEdit); +IMPORT_TEST_GROUP(test_MockADC); + +//START: main +int main(int argc, char** argv) +{ + return RUN_ALL_TESTS(argc, argv); +} +//END: main diff --git a/tests/RegEdit/CMakeLists.txt b/tests/RegEdit/CMakeLists.txt new file mode 100644 index 0000000..3a34794 --- /dev/null +++ b/tests/RegEdit/CMakeLists.txt @@ -0,0 +1,10 @@ +# TEST_RUNNER +add_library(test_RegEdit + test_RegEdit.cpp +) + +target_link_libraries(test_RegEdit + ${CPPUTEST_LIBRARIES}/libCppUTest.a + ${CPPUTEST_LIBRARIES}/libCppUTestExt.a + RegEdit +) diff --git a/tests/RegEdit/test_RegEdit.cpp b/tests/RegEdit/test_RegEdit.cpp new file mode 100644 index 0000000..c0bb7ca --- /dev/null +++ b/tests/RegEdit/test_RegEdit.cpp @@ -0,0 +1,32 @@ +/* + * Author: username + * Date: todays_date + * filename: test_RegEdit.c + * description: module_purpose + */ + +#include "CppUTest/CommandLineTestRunner.h" + +extern "C" +{ +#include "RegEdit.h" +} + +TEST_GROUP(test_RegEdit) +{ + void setup() + { + + } + void teardown() + { + + } +}; + +TEST(test_RegEdit, FirstTest) +{ + //FAIL("Fail me!"); + CHECK(true); +} +