generated from TDD-Templates/cmake_cpputest_template_avr
Compare commits
52 Commits
Author | SHA1 | Date |
---|---|---|
|
b64c306250 | |
|
deaa59f5a2 | |
|
91ee864d23 | |
|
78fdf54421 | |
|
c2ce883adb | |
|
60b83865cd | |
|
82c16a7ddc | |
|
33b70d3283 | |
|
de463a3469 | |
|
2add13a745 | |
|
6736e30dd1 | |
|
c07fc415bf | |
|
58ab3c12eb | |
|
fc3d0d11a5 | |
|
90891545d1 | |
|
352ee9e6a8 | |
|
969b852cb3 | |
|
a00e176675 | |
|
6167089a28 | |
|
b103fe2b97 | |
|
b377eab7c0 | |
|
43d15247ad | |
|
a29e16963f | |
|
d3d69ca180 | |
|
05b6de17d0 | |
|
b2a3dcbed4 | |
|
49d8ca037b | |
|
c2ed2cead0 | |
|
4d229a973c | |
|
cc57692a1d | |
|
ba4b6f9f70 | |
|
4dcfb1ea07 | |
|
4adeec5219 | |
|
17bd1a4e38 | |
|
b21a8fbecf | |
|
3f56d38e90 | |
|
d85616604f | |
|
28a5c50b23 | |
|
d455f80759 | |
|
3aaf0a066e | |
|
a5bb712789 | |
|
9228d0703f | |
|
39ce0af7fb | |
|
3f2eb09427 | |
|
de5cd13459 | |
|
a3d7307d96 | |
|
22c191363e | |
|
b96945a2a5 | |
|
2d65048f8e | |
|
bf39006dea | |
|
71ff471fde | |
|
724237147f |
|
@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
# Use the fancy version substitution
|
# Use the fancy version substitution
|
||||||
project(main
|
project(main
|
||||||
VERSION 0.1.2
|
VERSION 0.2.4
|
||||||
DESCRIPTION "template for cmake + cpputest"
|
DESCRIPTION "template for cmake + cpputest"
|
||||||
LANGUAGES C CXX
|
LANGUAGES C CXX
|
||||||
)
|
)
|
||||||
|
@ -38,7 +38,7 @@ set(CMAKE_CXX_FLAGS "-Wall -Werror -Wpedantic")
|
||||||
|
|
||||||
|
|
||||||
if (UNIT_TESTING)
|
if (UNIT_TESTING)
|
||||||
|
add_definitions(-DUNIT_TESTING)
|
||||||
if(DEFINED ENV{CPPUTEST_HOME})
|
if(DEFINED ENV{CPPUTEST_HOME})
|
||||||
message(STATUS "Using CppUTest home: $ENV{CPPUTEST_HOME}")
|
message(STATUS "Using CppUTest home: $ENV{CPPUTEST_HOME}")
|
||||||
set(CPPUTEST_INCLUDE_DIRS $ENV{CPPUTEST_HOME}/include)
|
set(CPPUTEST_INCLUDE_DIRS $ENV{CPPUTEST_HOME}/include)
|
||||||
|
@ -71,6 +71,7 @@ include_directories(
|
||||||
./inc
|
./inc
|
||||||
/usr/local/avr/include/avr
|
/usr/local/avr/include/avr
|
||||||
/usr/local/avr/include
|
/usr/local/avr/include
|
||||||
|
/usr/local/avr/avr/include #for Linux
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
|
@ -32,6 +32,10 @@ The position will now be saved into the EEPROM memory.
|
||||||
To automatically move the fader into the saved location preform a quick
|
To automatically move the fader into the saved location preform a quick
|
||||||
press of the button.
|
press of the button.
|
||||||
|
|
||||||
|
The speed can be adjusted by changing the input value of the speed pot. The
|
||||||
|
speed adjustment affects the on/off ratio of the motor and has a programmed
|
||||||
|
minimum speed value in the function to prevent endless looping.
|
||||||
|
|
||||||
|
|
||||||
## Building Project(Windows)
|
## Building Project(Windows)
|
||||||
|
|
||||||
|
|
|
@ -15,9 +15,11 @@ set(AVR_MCU attiny13a)
|
||||||
#set(AVR_MCU avr64dd28) # Newer DX series, avrxmega2
|
#set(AVR_MCU avr64dd28) # Newer DX series, avrxmega2
|
||||||
|
|
||||||
#set(F_CPU 16000000UL)
|
#set(F_CPU 16000000UL)
|
||||||
#set(F_CPU 8000000)
|
#set(F_CPU 8000000UL)
|
||||||
set(F_CPU 9600000)
|
#set(F_CPU 9600000UL)#AVR without prescaler
|
||||||
#set(F_CPU 4800000)
|
set(F_CPU 1200000UL) #AVR (9.6MHz) with prescaler 8DIV
|
||||||
|
#set(F_CPU 4800000UL) #AVR without prescaler
|
||||||
|
#set(F_CPU 600000UL) #AVR (4.8MHz) with prescaler 8DIV
|
||||||
|
|
||||||
add_compile_definitions(F_CPU=${F_CPU})
|
add_compile_definitions(F_CPU=${F_CPU})
|
||||||
# add_compile_definitions(MCU=atmega328p)
|
# add_compile_definitions(MCU=atmega328p)
|
||||||
|
|
|
@ -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 <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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
|
|
@ -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 <stdint.h>
|
||||||
|
|
||||||
|
#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
|
22
inc/main.h
22
inc/main.h
|
@ -10,6 +10,10 @@
|
||||||
#ifndef MAIN_H
|
#ifndef MAIN_H
|
||||||
#define MAIN_H
|
#define MAIN_H
|
||||||
|
|
||||||
|
#ifndef __AVR_ATtiny13A__
|
||||||
|
#define __AVR_ATtiny13A__
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,8 +32,8 @@
|
||||||
|
|
||||||
//Addresses in the eeprom for the two switch states
|
//Addresses in the eeprom for the two switch states
|
||||||
#define ROM_SP_ADR 0x0
|
#define ROM_SP_ADR 0x0
|
||||||
#define ROM_SS1_ADR 0x1
|
#define POSITION1_ADR 0x1
|
||||||
#define ROM_SS2_ADR 0x2
|
#define POSITION2_ADR 0x2
|
||||||
#define ROM_EP_ADR 0x3
|
#define ROM_EP_ADR 0x3
|
||||||
|
|
||||||
//Debounce check number.
|
//Debounce check number.
|
||||||
|
@ -42,8 +46,11 @@
|
||||||
#define PWM_PIN1 PB0 // Pin 5 - Motor PWM 1
|
#define PWM_PIN1 PB0 // Pin 5 - Motor PWM 1
|
||||||
#define PWM_PIN2 PB1 // Pin 6 - Motor PWM 2
|
#define PWM_PIN2 PB1 // Pin 6 - Motor PWM 2
|
||||||
#define ADC_PIN PB3 // Pin 2 - Fader position reading
|
#define ADC_PIN PB3 // Pin 2 - Fader position reading
|
||||||
|
#define SPEED_PIN PB2 // Pin 7/ADC1
|
||||||
#define BUTTON_PIN PB4 // Pin 3 - Button input
|
#define BUTTON_PIN PB4 // Pin 3 - Button input
|
||||||
|
|
||||||
|
#define MOTOR_PULSE 6 //uS motor base pulse
|
||||||
|
|
||||||
|
|
||||||
/*The timing of "ticks" is dependent on the AVR timer's counter register
|
/*The timing of "ticks" is dependent on the AVR timer's counter register
|
||||||
* so for an 8bit register the maximum value is 256. Given we stick with
|
* so for an 8bit register the maximum value is 256. Given we stick with
|
||||||
|
@ -82,7 +89,6 @@ typedef struct {
|
||||||
uint8_t timer_enabled: 1;
|
uint8_t timer_enabled: 1;
|
||||||
uint8_t pressed_ticks;
|
uint8_t pressed_ticks;
|
||||||
uint8_t input_pin;
|
uint8_t input_pin;
|
||||||
uint8_t output_pin;
|
|
||||||
}btn_state;
|
}btn_state;
|
||||||
|
|
||||||
|
|
||||||
|
@ -97,9 +103,15 @@ void InitProg(void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Reads the ADC pin
|
* @brief Reads the ADC pin from the fader.
|
||||||
*/
|
*/
|
||||||
uint16_t ReadADC(void);
|
uint16_t ReadFader(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads the ADC value from the Speed pot.
|
||||||
|
*/
|
||||||
|
uint8_t ReadSpeed(void);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
add_subdirectory(MockRegEdit)
|
||||||
|
add_subdirectory(MockADC)
|
||||||
|
add_subdirectory(TimerMock)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
add_library(MockADC STATIC
|
||||||
|
MockADC.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(MockADC PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Author: username
|
||||||
|
* Date: 2024
|
||||||
|
* filename: MockADC.c
|
||||||
|
* description: module_purpose
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MockADC.h"
|
||||||
|
#include "CppUTestExt/MockSupport_c.h"
|
||||||
|
|
||||||
|
#define FAKESIZE 256
|
||||||
|
|
||||||
|
uint16_t fake_data[FAKESIZE];
|
||||||
|
int fake_index = 0;
|
||||||
|
|
||||||
|
static bool is_setup = false;
|
||||||
|
|
||||||
|
|
||||||
|
void ADC_Setup(void)
|
||||||
|
{
|
||||||
|
is_setup = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_Init(uint8_t adc_chan)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("ADC_Init")
|
||||||
|
->withUnsignedIntParameters("adc_chan", adc_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_Enable(void)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("ADC_Enable");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_Disable()
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("ADC_Disable");
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ADC_ReadValue_Impl(void)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("ADC_ReadValue_Impl");
|
||||||
|
|
||||||
|
|
||||||
|
if(fake_index == 0){
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return fake_data[--fake_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t (*ADC_ReadValue)(void) = ADC_ReadValue_Impl;
|
||||||
|
|
||||||
|
|
||||||
|
void MockADC_PushValue(uint16_t value){
|
||||||
|
if(fake_index >= FAKESIZE - 1){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fake_data[fake_index++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void MockADC_ZeroIndex(void)
|
||||||
|
{
|
||||||
|
fake_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int MockADC_GetIndex(void)
|
||||||
|
{
|
||||||
|
return fake_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool MockADC_IsSetup(void)
|
||||||
|
{
|
||||||
|
return is_setup;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
/**
|
||||||
|
* @brief PUT_TEXT_HERE
|
||||||
|
* @details This file is...
|
||||||
|
* @author username
|
||||||
|
* @date todays_date
|
||||||
|
* @copyright None
|
||||||
|
* @file MOCKADC.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOCKADC_H
|
||||||
|
#define MOCKADC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
|
||||||
|
void ADC_Setup(void);
|
||||||
|
void ADC_Init(uint8_t adc_chan);
|
||||||
|
void ADC_Enable(void);
|
||||||
|
void ADC_Disable(void);
|
||||||
|
|
||||||
|
extern uint16_t (*ADC_ReadValue)(void);
|
||||||
|
|
||||||
|
void MockADC_PushValue(uint16_t value);
|
||||||
|
void MockADC_ZeroIndex(void);
|
||||||
|
int MockADC_GetIndex(void);
|
||||||
|
bool MockADC_IsSetup(void);
|
||||||
|
|
||||||
|
#endif //MOCKADC_H
|
|
@ -0,0 +1,12 @@
|
||||||
|
add_library(MockRegEdit STATIC
|
||||||
|
MockRegEdit.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(MockRegEdit PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(MockRegEdit
|
||||||
|
${CPPUTEST_LIBRARIES}/libCppUTest.a
|
||||||
|
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
|
||||||
|
)
|
|
@ -0,0 +1,85 @@
|
||||||
|
/*
|
||||||
|
* Author: username
|
||||||
|
* Date: 2024
|
||||||
|
* filename: MockRegEdit.c
|
||||||
|
* description: module_purpose
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MockRegEdit.h"
|
||||||
|
#include "CppUTestExt/MockSupport_c.h"
|
||||||
|
|
||||||
|
|
||||||
|
void RegEdit_SetRegister(void *reg)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("RegEdit_SetRegister")
|
||||||
|
->withPointerParameters("reg", reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegEdit_ClearRegister(void *reg)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("RegEdit_ClearRegister")
|
||||||
|
->withPointerParameters("reg", reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RegEdit_SetBit(void *reg, uint8_t bit_num)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("RegEdit_SetBit")
|
||||||
|
->withPointerParameters("reg", reg)
|
||||||
|
->withUnsignedIntParameters("bit_num", bit_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RegEdit_ClearBit(void *reg, uint8_t bit_num)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("RegEdit_ClearBit")
|
||||||
|
->withPointerParameters("reg", reg)
|
||||||
|
->withUnsignedIntParameters("bit_num", bit_num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool RegEdit_IsBitSet(void *reg, uint8_t bit_num)
|
||||||
|
{
|
||||||
|
|
||||||
|
return mock_c()->actualCall("RegEdit_IsBitSet")
|
||||||
|
->withPointerParameters("reg", reg)
|
||||||
|
->withUnsignedIntParameters("bit_num", bit_num)
|
||||||
|
->returnBoolValueOrDefault(true);
|
||||||
|
//return mock_c()->returnBoolValueOrDefault(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void RegEdit_OR_Num(void *reg, uint8_t num)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("RegEdit_OR_Num")
|
||||||
|
->withPointerParameters("reg", reg)
|
||||||
|
->withUnsignedIntParameters("num", num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void RegEdit_AND_Num(void *reg, uint8_t num)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("RegEdit_AND_Num")
|
||||||
|
->withPointerParameters("reg", reg)
|
||||||
|
->withUnsignedIntParameters("num", num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void RegEdit_SetNum(void *reg, uint8_t num)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("RegEdit_SetNum")
|
||||||
|
->withPointerParameters("reg", reg)
|
||||||
|
->withUnsignedIntParameters("num", num);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t RegEdit_ReadReg(void *reg)
|
||||||
|
{
|
||||||
|
uint8_t value = *(uint8_t *)reg;
|
||||||
|
|
||||||
|
mock_c()->actualCall("RegEdit_ReadReg")
|
||||||
|
->withPointerParameters("reg", reg)
|
||||||
|
->returnUnsignedIntValueOrDefault(value);
|
||||||
|
|
||||||
|
return value;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
/**
|
||||||
|
* @brief PUT_TEXT_HERE
|
||||||
|
* @details This file is...
|
||||||
|
* @author username
|
||||||
|
* @date todays_date
|
||||||
|
* @copyright None
|
||||||
|
* @file MockRegEdit.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MOCKREGEDIT_H
|
||||||
|
#define MOCKREGEDIT_H
|
||||||
|
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
void RegEdit_SetRegister(void *reg);
|
||||||
|
void RegEdit_ClearRegister(void *reg);
|
||||||
|
void RegEdit_SetBit(void *reg, uint8_t bit_num);
|
||||||
|
void RegEdit_ClearBit(void *reg, uint8_t bit_num);
|
||||||
|
bool RegEdit_IsBitSet(void *reg, uint8_t bit_num);
|
||||||
|
|
||||||
|
void RegEdit_OR_Num(void *reg, uint8_t num);
|
||||||
|
void RegEdit_AND_Num(void *reg, uint8_t num);
|
||||||
|
|
||||||
|
void RegEdit_SetNum(void *reg, uint8_t num);
|
||||||
|
|
||||||
|
uint8_t RegEdit_ReadReg(void *reg);
|
||||||
|
|
||||||
|
#endif //MOCKREGEDIT_H
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "u8_comparator.hpp"
|
||||||
|
#include "CppUTest/SimpleString.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
class MyTypeComparator : public MockNamedValueComparator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool isEqual(const void* object1, const void* object2)
|
||||||
|
{
|
||||||
|
return object1 == object2;
|
||||||
|
}
|
||||||
|
virtual SimpleString valueToString(const void* object)
|
||||||
|
{
|
||||||
|
return StringFrom(object);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool UInt8PointerComparator::isEqual(const void* object1, const void* object2) {
|
||||||
|
const uint8_t* ptr1 = reinterpret_cast<const uint8_t*>(object1);
|
||||||
|
const uint8_t* ptr2 = reinterpret_cast<const uint8_t*>(object2);
|
||||||
|
return std::memcmp(ptr1, ptr2, sizeof(uint8_t)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleString UInt8PointerComparator::valueToString(const void* object) {
|
||||||
|
const uint8_t* ptr = reinterpret_cast<const uint8_t*>(object);
|
||||||
|
return StringFromFormat("0x%02x", *ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
bool UInt8PointerComparator::isEqual(const void* object1, const void* object2) const {
|
||||||
|
const uint8_t* ptr1 = static_cast<const uint8_t*>(object1);
|
||||||
|
const uint8_t* ptr2 = static_cast<const uint8_t*>(object2);
|
||||||
|
return std::memcmp(ptr1, ptr2, sizeof(uint8_t)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleString UInt8PointerComparator::valueToString(const void* object) const {
|
||||||
|
const uint8_t* ptr = static_cast<const uint8_t*>(object);
|
||||||
|
return StringFromFormat("0x%02x", *ptr);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool UInt8Comparator::isEqual(const void* object1, const void* object2) {
|
||||||
|
return (uint8_t*)object1 == (uint8_t *)object2;
|
||||||
|
}
|
||||||
|
|
||||||
|
SimpleString UInt8Comparator::valueToString(const void* object) {
|
||||||
|
//uint8_t value = reinterpret_cast<uint8_t>(object);
|
||||||
|
const uint8_t *ptr = reinterpret_cast<const uint8_t*>(object);
|
||||||
|
return StringFromFormat("0x%02x", *ptr);
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef U8_COMPARATOR_H
|
||||||
|
#define U8_COMPARATOR_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstring>
|
||||||
|
#include <CppUTestExt/MockSupport.h>
|
||||||
|
|
||||||
|
class UInt8PointerComparator : public MockNamedValueComparator {
|
||||||
|
public:
|
||||||
|
virtual bool isEqual(const void* object1, const void* object2) override;
|
||||||
|
SimpleString valueToString(const void* object) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UInt8Comparator : public MockNamedValueComparator {
|
||||||
|
public:
|
||||||
|
virtual bool isEqual(const void* object1, const void* object2) override;
|
||||||
|
SimpleString valueToString(const void* object) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //U8_COMPARATOR_H
|
|
@ -0,0 +1,7 @@
|
||||||
|
add_library(TimerMock STATIC
|
||||||
|
TimerMock.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(TimerMock PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Author: Jake G
|
||||||
|
* Date: 2024-09-02
|
||||||
|
* filename: TimerMock.c
|
||||||
|
* description: mocks timers
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "TimerMock.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "CppUTestExt/MockSupport_c.h"
|
||||||
|
|
||||||
|
static bool timer_started = false;
|
||||||
|
|
||||||
|
void Timer_Start(void)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("Timer_Start");
|
||||||
|
timer_started = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Timer_Stop(void)
|
||||||
|
{
|
||||||
|
mock_c()->actualCall("Timer_Stop");
|
||||||
|
timer_started = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t Timer_GetOverflowCount(void)
|
||||||
|
{
|
||||||
|
uint16_t time = 0xAAAA;
|
||||||
|
return mock_c()->actualCall("Timer_GetOverflowCount")
|
||||||
|
->returnUnsignedIntValueOrDefault(time);
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/**
|
||||||
|
* @brief A Mock of the timer module.
|
||||||
|
* @details This file is only used for testing.
|
||||||
|
* @author Jake G
|
||||||
|
* @date 2024-09-02
|
||||||
|
* @copyright None
|
||||||
|
* @file TimerMock.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TIMER_MOCK_H
|
||||||
|
#define TIMER_MOCK_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A function
|
||||||
|
* @param a The first argument
|
||||||
|
*/
|
||||||
|
void Timer_Start(void);
|
||||||
|
|
||||||
|
void Timer_Stop(void);
|
||||||
|
|
||||||
|
uint16_t Timer_GetOverflowCount(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif //TIMER_MOCK_H
|
11
otto.sh
11
otto.sh
|
@ -224,12 +224,19 @@ run_c_tests () {
|
||||||
make AllTests && ./tests/AllTests -c -v
|
make AllTests && ./tests/AllTests -c -v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
run_mock_tests () {
|
||||||
|
format_source_code
|
||||||
|
clear_cmake_cache
|
||||||
|
cmake -DUNIT_TESTING=ON -DCMAKE_VERBOSE_MAKEFILE=${CMAKE_VERBOSE} ../
|
||||||
|
make Mock_Tests && ./tests/Mock_Tests -c -v
|
||||||
|
}
|
||||||
|
|
||||||
print_menu () {
|
print_menu () {
|
||||||
echo "BUILD MENU:"
|
echo "BUILD MENU:"
|
||||||
echo "0. Add Mock Module"
|
echo "0. Add Mock Module"
|
||||||
echo "1. Run Tests"
|
echo "1. Run Tests"
|
||||||
echo "2. Build Project(hex)"
|
echo "2. Build Project(hex)"
|
||||||
echo "3. User Option"
|
echo "3. Run MockTests"
|
||||||
echo "4. Flash to AVR"
|
echo "4. Flash to AVR"
|
||||||
echo "5. Add new module to project"
|
echo "5. Add new module to project"
|
||||||
echo "6. Delete module from project"
|
echo "6. Delete module from project"
|
||||||
|
@ -264,7 +271,7 @@ main() {
|
||||||
3)
|
3)
|
||||||
echo "You selected Option 3"
|
echo "You selected Option 3"
|
||||||
valid_choice=true
|
valid_choice=true
|
||||||
build_hex_optimized
|
run_mock_tests
|
||||||
;;
|
;;
|
||||||
4)
|
4)
|
||||||
echo "You selected Option 4"
|
echo "You selected Option 4"
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
/*
|
||||||
|
* Author: Jake G
|
||||||
|
* Date: 2025
|
||||||
|
* filename: ADC.c
|
||||||
|
* description: module_purpose
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AVR_ATtiny13A__
|
||||||
|
#define __AVR_ATtiny13A__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "ADC.h"
|
||||||
|
#include "RegEdit.h"
|
||||||
|
#include "avr/io.h"
|
||||||
|
|
||||||
|
#define MAX_CHANNEL_NUM 3
|
||||||
|
|
||||||
|
static bool IsInvalidChannel(uint8_t adc_chan) {
|
||||||
|
if (adc_chan > MAX_CHANNEL_NUM) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ADC_GetChannelPinNum(uint8_t adc_chan) {
|
||||||
|
switch (adc_chan) {
|
||||||
|
case 0:
|
||||||
|
return PB5;
|
||||||
|
case 1:
|
||||||
|
return PB2;
|
||||||
|
case 2:
|
||||||
|
return PB4;
|
||||||
|
case 3:
|
||||||
|
return PB3;
|
||||||
|
default:
|
||||||
|
return 255; /*return invalid pin num.*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_Setup(void) {
|
||||||
|
// Clear the register, set VCC as ref, ADC0 as channel and
|
||||||
|
// leave result right adjusted.
|
||||||
|
RegEdit_ClearRegister((void *)&ADMUX);
|
||||||
|
|
||||||
|
// Status & Control register A
|
||||||
|
// Turn on the 8Div prescaler
|
||||||
|
RegEdit_SetNum((void *)&ADCSRA, (1 << ADPS1) | (1 << ADPS0));
|
||||||
|
|
||||||
|
// Status & Control register B
|
||||||
|
// Turn on auto-trigger using time compare/match B.
|
||||||
|
RegEdit_AND_Num((void *)&ADCSRB, (1 << ADTS2) | (0 << ADTS1) | (1 << ADTS0));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_Init(uint8_t adc_chan) {
|
||||||
|
|
||||||
|
if (IsInvalidChannel(adc_chan)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the associated pin number.
|
||||||
|
uint8_t pin_num = ADC_GetChannelPinNum(adc_chan);
|
||||||
|
|
||||||
|
// set the direction to input
|
||||||
|
RegEdit_ClearBit((void *)&DDRB, pin_num);
|
||||||
|
|
||||||
|
// Disable the pull-up resistor
|
||||||
|
RegEdit_ClearBit((void *)&PORTB, pin_num);
|
||||||
|
|
||||||
|
// Set the adc mux reg for our channel.
|
||||||
|
|
||||||
|
// Clear the existing mux bits.
|
||||||
|
RegEdit_AND_Num((void *)&ADMUX, 0xFC);
|
||||||
|
|
||||||
|
// Set the correct bits
|
||||||
|
RegEdit_OR_Num((void *)&ADMUX, adc_chan);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_Enable(void) {
|
||||||
|
// Set the enable bit in the CTRLA register
|
||||||
|
RegEdit_SetBit((void *)&ADCSRA, ADEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADC_Disable() {
|
||||||
|
// Clear the enable ADC flag
|
||||||
|
RegEdit_ClearBit((void *)&ADCSRA, ADEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t ADC_ReadValue_Impl(void) {
|
||||||
|
|
||||||
|
// start conversion.
|
||||||
|
RegEdit_SetBit((void *)&ADCSRA, ADSC);
|
||||||
|
|
||||||
|
/* Wait until ADC conversion done or it times out. */
|
||||||
|
uint8_t cycles = 1;
|
||||||
|
while (1) {
|
||||||
|
if (!RegEdit_IsBitSet((void *)&ADCSRA, ADSC)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// if It times out return an invalid value for a 12bit ADC.
|
||||||
|
else if (cycles >= ADC_WAIT_TIMEOUT) {
|
||||||
|
return UINT16_MAX;
|
||||||
|
}
|
||||||
|
cycles++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t val = ADC;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the default for the function pointer.
|
||||||
|
uint16_t (*ADC_ReadValue)(void) = ADC_ReadValue_Impl;
|
|
@ -0,0 +1,72 @@
|
||||||
|
/**
|
||||||
|
* @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 <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief The number of loop cycles it waits for ADC conversion before
|
||||||
|
* timing out.
|
||||||
|
*/
|
||||||
|
#define ADC_WAIT_TIMEOUT 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the AVR hardware in order to accept
|
||||||
|
* Input for ADC usage.
|
||||||
|
* @param adc_chan The channel 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 adc_chan);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the pin number for the adc channel or 255 on an error.
|
||||||
|
* @param The ADC channel.
|
||||||
|
*/
|
||||||
|
uint8_t ADC_GetChannelPinNum(uint8_t adc_chan);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enables the ADC
|
||||||
|
*/
|
||||||
|
void ADC_Enable(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Disables the ADC
|
||||||
|
*/
|
||||||
|
void ADC_Disable();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads ADC value into variable
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* This function depends on the ADC already being initialized and enabled
|
||||||
|
* before being called.
|
||||||
|
*/
|
||||||
|
extern uint16_t (*ADC_ReadValue)();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
#endif // ADC_H
|
|
@ -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()
|
|
@ -2,6 +2,12 @@ add_executable(${PROJECT_NAME}
|
||||||
main.c
|
main.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${PROJECT_NAME}
|
||||||
|
#RegEdit
|
||||||
|
#ADC
|
||||||
|
#timer
|
||||||
|
)
|
||||||
|
|
||||||
# Ensure the build rules are defined
|
# Ensure the build rules are defined
|
||||||
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
|
set_target_properties(${PROJECT_NAME} PROPERTIES SUFFIX ".elf")
|
||||||
|
|
||||||
|
@ -31,10 +37,17 @@ add_custom_target(bin ALL
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Setup for default 9.6MHz
|
||||||
if(NOT TARGET upload)
|
if(NOT TARGET upload)
|
||||||
# Upload command (adjust according to your programmer)
|
# Upload command (adjust according to your programmer)
|
||||||
add_custom_target(upload ALL
|
add_custom_target(upload ALL
|
||||||
COMMAND avrdude -c ${PROGRAMMER} -P ${PORT} -p ${AVR_MCU} -B 125kHz -U flash:w:${CMAKE_PROJECT_NAME}.hex
|
COMMAND avrdude -c ${PROGRAMMER} -P ${PORT} -p ${AVR_MCU} -B 125kHz -U lfuse:w:0x6a:m -U hfuse:w:0xFF:m -U lock:w:0xFF:m -U flash:w:${CMAKE_PROJECT_NAME}.hex
|
||||||
DEPENDS hex
|
DEPENDS hex
|
||||||
)
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
add_subdirectory(RegEdit)
|
||||||
|
add_subdirectory(timer)
|
||||||
|
add_subdirectory(SuperLoop)
|
||||||
|
add_subdirectory(ADC)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
add_library(RegEdit STATIC
|
||||||
|
RegEdit.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(RegEdit PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
|
@ -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;
|
||||||
|
}
|
|
@ -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 <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @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
|
|
@ -0,0 +1,7 @@
|
||||||
|
add_library(SuperLoop STATIC
|
||||||
|
SuperLoop.c
|
||||||
|
)
|
||||||
|
|
||||||
|
target_include_directories(SuperLoop PUBLIC
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}
|
||||||
|
)
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
* Author: Jake G
|
||||||
|
* Date: 2024-09-01
|
||||||
|
* filename: SuperLoop.c
|
||||||
|
* description: The RT super loop.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "SuperLoop.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
|
@ -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 <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
84
src/main.c
84
src/main.c
|
@ -1,14 +1,15 @@
|
||||||
#ifndef F_CPU
|
#ifndef F_CPU
|
||||||
#define F_CPU 4800000UL
|
#define F_CPU 1200000UL
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
//#include "ADC.h"
|
||||||
#include <avr/eeprom.h>
|
#include <avr/eeprom.h>
|
||||||
#include <avr/interrupt.h>
|
#include <avr/interrupt.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
|
|
||||||
// These are only included during development for the LSP server.
|
// These are only included during development for the LSP server.
|
||||||
//#include "iotn13.h"
|
// #include "iotn13.h"
|
||||||
// #include "iotn13a.h"
|
// #include "iotn13a.h"
|
||||||
|
|
||||||
// #############################
|
// #############################
|
||||||
|
@ -32,7 +33,7 @@ volatile uint16_t tick_count;
|
||||||
// #############################
|
// #############################
|
||||||
|
|
||||||
static inline void InitTimer0(void);
|
static inline void InitTimer0(void);
|
||||||
static void InitBtn(btn_state *b, uint8_t input_pin, uint8_t output_pin);
|
static void InitBtn(btn_state *b, uint8_t input_pin);
|
||||||
static void ClearButtonTimer(btn_state *b);
|
static void ClearButtonTimer(btn_state *b);
|
||||||
static void StartButtonTimer(btn_state *b);
|
static void StartButtonTimer(btn_state *b);
|
||||||
static void CheckButtonLongpress(btn_state *b);
|
static void CheckButtonLongpress(btn_state *b);
|
||||||
|
@ -62,7 +63,7 @@ void InitProg(void) {
|
||||||
/*Set the debounced state to all high*/
|
/*Set the debounced state to all high*/
|
||||||
debounced_state = 0xFF;
|
debounced_state = 0xFF;
|
||||||
|
|
||||||
InitBtn(&btn1, BUTTON_PIN, PIN_ACTIVE1);
|
InitBtn(&btn1, BUTTON_PIN);
|
||||||
|
|
||||||
/*Wait 5ms for pull-up resistors voltage to become stable.*/
|
/*Wait 5ms for pull-up resistors voltage to become stable.*/
|
||||||
_delay_ms(5);
|
_delay_ms(5);
|
||||||
|
@ -73,17 +74,37 @@ void InitProg(void) {
|
||||||
|
|
||||||
// Checks against a bit pattern we defined to represent the start of data.
|
// Checks against a bit pattern we defined to represent the start of data.
|
||||||
if (eeprom_read_byte((uint8_t *)ROM_SP_ADR) == START_PATTERN) {
|
if (eeprom_read_byte((uint8_t *)ROM_SP_ADR) == START_PATTERN) {
|
||||||
MotorMoveTo(eeprom_read_byte((uint8_t *)ROM_SS1_ADR));
|
MotorMoveTo(eeprom_read_byte((uint8_t *)POSITION1_ADR));
|
||||||
} else {
|
} else {
|
||||||
// otherwise we write the init values for the start pattern and states.
|
// otherwise we write the init values for the start pattern and states.
|
||||||
eeprom_write_byte((uint8_t *)ROM_SP_ADR, START_PATTERN);
|
eeprom_write_byte((uint8_t *)ROM_SP_ADR, START_PATTERN);
|
||||||
eeprom_write_byte((uint8_t *)ROM_SS1_ADR, 0x7F);
|
eeprom_write_byte((uint8_t *)POSITION1_ADR, 0x7F);
|
||||||
}
|
}
|
||||||
|
|
||||||
InitTimer0();
|
InitTimer0();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ReadADC(void) {
|
uint8_t ReadSpeed(void) {
|
||||||
|
// Initialize ADC
|
||||||
|
|
||||||
|
ADMUX = (0 << MUX1) | (1 << MUX0); // Select ADC1 (PB2)
|
||||||
|
ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, prescaler 8
|
||||||
|
|
||||||
|
ADCSRA |= (1 << ADSC); // Start conversion
|
||||||
|
while (ADCSRA & (1 << ADSC)) {
|
||||||
|
} // Wait for conversion to finish
|
||||||
|
|
||||||
|
//Normally a bitshift of 2 is done for 8bit ADC values,
|
||||||
|
//however we want to divide by two after this as well so we
|
||||||
|
//do a third shift followed by an addition of 127 to yield a mapping of
|
||||||
|
//approximatly 50%-96.6% duty cycle range.
|
||||||
|
uint8_t val = (uint8_t)(ADC >> 3) + 127;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
// change to ReadFader(void)
|
||||||
|
uint16_t ReadFader(void) {
|
||||||
// Initialize ADC
|
// Initialize ADC
|
||||||
ADMUX = (1 << MUX1) | (1 << MUX0); // Select ADC3 (PB3)
|
ADMUX = (1 << MUX1) | (1 << MUX0); // Select ADC3 (PB3)
|
||||||
ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, prescaler 8
|
ADCSRA = (1 << ADEN) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC, prescaler 8
|
||||||
|
@ -107,22 +128,26 @@ static inline uint8_t diff(uint8_t a, uint8_t b) {
|
||||||
return b - a;
|
return b - a;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorSetSavePos() {
|
void MotorSetSavePos(uint8_t *ADR) {
|
||||||
uint8_t pos = (uint8_t)(ReadADC() >> 2);
|
uint8_t pos = (uint8_t)(ReadFader() >> 2);
|
||||||
eeprom_write_byte((uint8_t *)ROM_SS1_ADR, pos);
|
//eeprom_write_byte((uint8_t *)ADR, pos);
|
||||||
|
eeprom_update_byte((uint8_t *)ADR, pos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t MotorGetSavedPos(void) {
|
uint8_t MotorGetSavedPos(uint8_t *ADR) {
|
||||||
return (uint8_t)eeprom_read_byte((uint8_t *)ROM_SS1_ADR);
|
return (uint8_t)eeprom_read_byte((uint8_t *)POSITION1_ADR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MotorMoveTo(uint8_t target) {
|
void MotorMoveTo(uint8_t target) {
|
||||||
|
|
||||||
uint8_t pos = (uint8_t)(ReadADC() >> 2);
|
uint8_t on_delay = ReadSpeed();
|
||||||
|
uint8_t pos = (uint8_t)(ReadFader() >> 2);
|
||||||
|
uint8_t idx = 0;
|
||||||
|
|
||||||
while (diff(target, pos) > 8) {
|
while (diff(target, pos) > 8) {
|
||||||
pos = (uint8_t)(ReadADC() >> 2);
|
on_delay = ReadSpeed();
|
||||||
|
pos = (uint8_t)(ReadFader() >> 2);
|
||||||
if (target > pos) {
|
if (target > pos) {
|
||||||
MotorMove(1);
|
MotorMove(1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -130,15 +155,20 @@ void MotorMoveTo(uint8_t target) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// The delay ratio controlls the PWM waveforms.
|
// The delay ratio controlls the PWM waveforms.
|
||||||
//_delay_ms(5);
|
for (idx = 0; idx < on_delay; idx++) {
|
||||||
// MotorCoast();
|
_delay_us(MOTOR_PULSE);
|
||||||
// _delay_ms(5);
|
}
|
||||||
|
MotorCoast();
|
||||||
|
for (; idx < 255; idx++) {
|
||||||
|
_delay_us(MOTOR_PULSE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using the compatable bool type.
|
// Using the compatable bool type.
|
||||||
|
// The motor being used seems to stop working below a 50% duty cycle.
|
||||||
void MotorMove(uint8_t fwd) {
|
void MotorMove(uint8_t fwd) {
|
||||||
if (fwd) {
|
if (fwd) {
|
||||||
PORTB |= (1 << PWM_PIN1);
|
PORTB |= (1 << PWM_PIN1);
|
||||||
|
@ -161,21 +191,17 @@ void MotorCoast(void) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*This is kinda like our button constructor*/
|
/*This is kinda like our button constructor*/
|
||||||
static void InitBtn(btn_state *b, uint8_t input_pin, uint8_t output_pin) {
|
static void InitBtn(btn_state *b, uint8_t input_pin) {
|
||||||
b->is_long_pressed = 0;
|
b->is_long_pressed = 0;
|
||||||
b->is_pressed = 0;
|
b->is_pressed = 0;
|
||||||
b->is_active = 0;
|
b->is_active = 0;
|
||||||
b->pressed_ticks = 0;
|
b->pressed_ticks = 0;
|
||||||
b->timer_enabled = 0;
|
b->timer_enabled = 0;
|
||||||
b->input_pin = input_pin;
|
b->input_pin = input_pin;
|
||||||
b->output_pin = output_pin;
|
|
||||||
|
|
||||||
/*Configure the buttons inputs and outputs*/
|
/*Configure the buttons inputs and outputs*/
|
||||||
DDRB &= ~(1 << b->input_pin);
|
DDRB &= ~(1 << b->input_pin);
|
||||||
PORTB |= (1 << b->input_pin);
|
PORTB |= (1 << b->input_pin);
|
||||||
|
|
||||||
DDRB |= (1 << b->output_pin);
|
|
||||||
PORTB &= ~(1 << b->output_pin);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ClearButtonTimer(btn_state *b) {
|
static void ClearButtonTimer(btn_state *b) {
|
||||||
|
@ -219,6 +245,7 @@ static void UpdateButtonOutput(btn_state *b) {
|
||||||
/*Then start the timer and update the output*/
|
/*Then start the timer and update the output*/
|
||||||
// ToggleOutput(b);
|
// ToggleOutput(b);
|
||||||
StartButtonTimer(b);
|
StartButtonTimer(b);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,12 +265,21 @@ static void UpdateButtonOutput(btn_state *b) {
|
||||||
else if (!b->is_pressed) {
|
else if (!b->is_pressed) {
|
||||||
/*If the button was released on a long press.*/
|
/*If the button was released on a long press.*/
|
||||||
if (b->is_long_pressed) {
|
if (b->is_long_pressed) {
|
||||||
MotorSetSavePos();
|
MotorSetSavePos((uint8_t *)POSITION1_ADR);
|
||||||
}
|
}
|
||||||
/*If the button pres was a short one.*/
|
/*If the button pres was a short one.*/
|
||||||
else if (!b->is_long_pressed) {
|
else if (!b->is_long_pressed) {
|
||||||
if (b->is_active) {
|
if (b->is_active) {
|
||||||
MotorMoveTo(MotorGetSavedPos());
|
/*Save the current position into position 2 EEPROM*/
|
||||||
|
MotorSetSavePos((uint8_t *)POSITION2_ADR);
|
||||||
|
|
||||||
|
/*If already in saved position then go back to original pos.*/
|
||||||
|
if(diff(MotorGetSavedPos((uint8_t *)POSITION1_ADR), ReadFader()) > 8){
|
||||||
|
MotorMoveTo(MotorGetSavedPos((uint8_t *)POSITION1_ADR));
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
MotorMoveTo(MotorGetSavedPos((uint8_t *)POSITION1_ADR));
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
MotorCoast();
|
MotorCoast();
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
|
@ -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 <avr/interrupt.h>
|
||||||
|
#include <avr/io.h>
|
||||||
|
|
||||||
|
#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();
|
||||||
|
}
|
|
@ -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
|
|
@ -0,0 +1,18 @@
|
||||||
|
# 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/local/avr/avr/include #for Linux
|
||||||
|
#/usr/lib/avr/include/avr
|
||||||
|
)
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
* Author: Jake G
|
||||||
|
* Date: 2025
|
||||||
|
* filename: test_ADC.c
|
||||||
|
* description: module_purpose
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUTest/CommandLineTestRunner.h"
|
||||||
|
#include "CppUTestExt/MockSupport.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
//This define allows us to dircetly include the device header without error.
|
||||||
|
#define _AVR_IO_H_
|
||||||
|
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "sfr_defs.h"
|
||||||
|
#include <iotn13a.h> //ATtiny13A header file.
|
||||||
|
#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)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* ADC Channel Selection(MUX1, MUX0):
|
||||||
|
* 00 == ADC0/PB5
|
||||||
|
* 01 == ADC1/PB2
|
||||||
|
* 10 == ADC2/PB4
|
||||||
|
* 11 == ADC3/PB3
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*Set the ADC Channel 0 (default) using ADMUX reg*/
|
||||||
|
/*Set the voltage reference to VCC.*/
|
||||||
|
/*Set ADC Left adjust result setting to off.*/
|
||||||
|
mock().expectOneCall("RegEdit_ClearRegister")
|
||||||
|
.withPointerParameter("reg", (void *) &ADMUX);
|
||||||
|
|
||||||
|
/*ADC0 Status and Control Register A*/
|
||||||
|
|
||||||
|
/*Set the Prescaler (F_CPU/8) for samping frequency.*/
|
||||||
|
mock().expectOneCall("RegEdit_SetNum")
|
||||||
|
.withPointerParameter("reg", (void *) &ADCSRA)
|
||||||
|
.withUnsignedIntParameter("num", 3);
|
||||||
|
|
||||||
|
|
||||||
|
/*ADC0 Status and Control Register B*/
|
||||||
|
|
||||||
|
/*Setup the auto-trigger source.*/
|
||||||
|
/*Using timer compare/match B for now.*/
|
||||||
|
mock().expectOneCall("RegEdit_AND_Num")
|
||||||
|
.withPointerParameter("reg", (void *) &ADCSRB)
|
||||||
|
.withUnsignedIntParameter("num", 5);
|
||||||
|
|
||||||
|
ADC_Setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(test_ADC, ADC_InitRejectsInvalidChannels)
|
||||||
|
{
|
||||||
|
for(uint8_t i = 4; i < 255; i++){
|
||||||
|
ADC_Init(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(test_ADC, ADC_InitPortbWorksWithValidChannels)
|
||||||
|
{
|
||||||
|
uint8_t pin_num;
|
||||||
|
|
||||||
|
for(uint8_t adc_channel = 0; adc_channel <= 3; adc_channel++)
|
||||||
|
{
|
||||||
|
pin_num = ADC_GetChannelPinNum(adc_channel);
|
||||||
|
|
||||||
|
//Check it disables the pin's digital circuitry
|
||||||
|
|
||||||
|
//Check it sets the pin for input
|
||||||
|
mock().expectOneCall("RegEdit_ClearBit")
|
||||||
|
.withPointerParameter("reg", (void *) &DDRB)
|
||||||
|
.withUnsignedIntParameter("bit_num", pin_num);
|
||||||
|
|
||||||
|
|
||||||
|
//Check that the pull-up resistor is disabled.
|
||||||
|
mock().expectOneCall("RegEdit_ClearBit")
|
||||||
|
.withPointerParameter("reg", (void *) &PORTB)
|
||||||
|
.withUnsignedIntParameter("bit_num", pin_num);
|
||||||
|
|
||||||
|
|
||||||
|
//Check that the ADC pin is selected in ADMUX
|
||||||
|
|
||||||
|
//Clears the last two bits first.
|
||||||
|
mock().expectOneCall("RegEdit_AND_Num")
|
||||||
|
.withPointerParameter("reg", (void *) &ADMUX)
|
||||||
|
.withUnsignedIntParameter("num", 0xFC);
|
||||||
|
|
||||||
|
//Selects the ADC pin/channel
|
||||||
|
mock().expectOneCall("RegEdit_OR_Num")
|
||||||
|
.withPointerParameter("reg", (void *) &ADMUX)
|
||||||
|
.withUnsignedIntParameter("num", adc_channel);
|
||||||
|
|
||||||
|
ADC_Init(adc_channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(test_ADC, ADC_EnablePasses)
|
||||||
|
{
|
||||||
|
|
||||||
|
mock().expectOneCall("RegEdit_SetBit")
|
||||||
|
.withPointerParameter("reg", (void *) &ADCSRA)
|
||||||
|
.withUnsignedIntParameter("bit_num", ADEN);
|
||||||
|
|
||||||
|
ADC_Enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TEST(test_ADC, ADC_DisablePasses)
|
||||||
|
{
|
||||||
|
mock().expectOneCall("RegEdit_ClearBit")
|
||||||
|
.withPointerParameter("reg", (void *) &ADCSRA)
|
||||||
|
.withUnsignedIntParameter("bit_num", ADEN);
|
||||||
|
|
||||||
|
ADC_Disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(test_ADC, ADC_ReadValueImplimentationTimesOut)
|
||||||
|
{
|
||||||
|
//Expect the start conversion bit to be set.
|
||||||
|
mock().expectOneCall("RegEdit_SetBit")
|
||||||
|
.withPointerParameter("reg", (void *) &ADCSRA)
|
||||||
|
.withUnsignedIntParameter("bit_num", ADSC);
|
||||||
|
|
||||||
|
//Check that it can time out.
|
||||||
|
|
||||||
|
//Expect it to read the start bit
|
||||||
|
mock().expectNCalls(ADC_WAIT_TIMEOUT, "RegEdit_IsBitSet")
|
||||||
|
.withPointerParameter("reg", (void *) &ADCSRA)
|
||||||
|
.withUnsignedIntParameter("bit_num", ADSC);
|
||||||
|
|
||||||
|
//Check that it return the "error" value
|
||||||
|
|
||||||
|
uint16_t value = ADC_ReadValue();
|
||||||
|
CHECK_EQUAL_TEXT(UINT16_MAX, value, "ERROR: Should return UINT16_MAX!");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static uint16_t ADC_ReadValueFake()
|
||||||
|
{
|
||||||
|
return 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_GROUP(test_ADCReadPtrSwap)
|
||||||
|
{
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
UT_PTR_SET(ADC_ReadValue, ADC_ReadValueFake);
|
||||||
|
}
|
||||||
|
|
||||||
|
void teardown()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TEST(test_ADCReadPtrSwap, FunctionPointerSwapWorks)
|
||||||
|
{
|
||||||
|
uint16_t value = ADC_ReadValue();
|
||||||
|
|
||||||
|
LONGS_EQUAL(512, value);
|
||||||
|
}
|
||||||
|
|
|
@ -3,6 +3,10 @@
|
||||||
|
|
||||||
//ImportTestGroups
|
//ImportTestGroups
|
||||||
IMPORT_TEST_GROUP(simple_test);
|
IMPORT_TEST_GROUP(simple_test);
|
||||||
|
IMPORT_TEST_GROUP(test_SuperLoop);
|
||||||
|
IMPORT_TEST_GROUP(test_ADC);
|
||||||
|
IMPORT_TEST_GROUP(test_RegEdit);
|
||||||
|
|
||||||
|
|
||||||
//START: main
|
//START: main
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
|
|
|
@ -1,7 +1,13 @@
|
||||||
project(Tests)
|
project(Tests)
|
||||||
|
|
||||||
# TEST_DIRS
|
# TEST_DIRS
|
||||||
|
add_subdirectory(SuperLoop)
|
||||||
|
add_subdirectory(ADC)
|
||||||
|
add_subdirectory(MockADC)
|
||||||
|
add_subdirectory(RegEdit)
|
||||||
|
add_subdirectory(MockRegEdit)
|
||||||
add_subdirectory(simple_test)
|
add_subdirectory(simple_test)
|
||||||
|
#add_subdirectory(timer)
|
||||||
|
|
||||||
# TEST_RUNNER
|
# TEST_RUNNER
|
||||||
add_executable(AllTests
|
add_executable(AllTests
|
||||||
|
@ -12,5 +18,19 @@ target_link_libraries(AllTests
|
||||||
${CPPUTEST_LIBRARIES}/libCppUTest.a
|
${CPPUTEST_LIBRARIES}/libCppUTest.a
|
||||||
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
|
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
|
||||||
# TEST_LINKS
|
# TEST_LINKS
|
||||||
|
test_SuperLoop
|
||||||
|
test_ADC
|
||||||
|
test_RegEdit
|
||||||
simple_test
|
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
|
||||||
|
)
|
||||||
|
|
|
@ -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
|
||||||
|
)
|
|
@ -0,0 +1,92 @@
|
||||||
|
/*
|
||||||
|
* Author: Jake G
|
||||||
|
* Date: 2024
|
||||||
|
* filename: test_MockADC.c
|
||||||
|
* description:
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUTest/CommandLineTestRunner.h"
|
||||||
|
#include "CppUTestExt/MockSupport.h"
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
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("adc_chan", 0);
|
||||||
|
|
||||||
|
ADC_Init(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
|
||||||
|
uint16_t val = ADC_ReadValue();
|
||||||
|
LONGS_EQUAL(512, val);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(test_MockADC, ADC_ReadValueReturnsZeroOnEmptyBuffer)
|
||||||
|
{
|
||||||
|
MockADC_ZeroIndex();
|
||||||
|
|
||||||
|
mock().expectOneCall("ADC_ReadValue_Impl")
|
||||||
|
.andReturnValue(0x0000);
|
||||||
|
|
||||||
|
uint16_t val = ADC_ReadValue();
|
||||||
|
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());
|
||||||
|
}
|
|
@ -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
|
||||||
|
)
|
||||||
|
|
|
@ -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 <cstdint>
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
|
@ -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
|
|
@ -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
|
||||||
|
)
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
# TEST_RUNNER
|
||||||
|
add_library(test_SuperLoop
|
||||||
|
test_SuperLoop.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(test_SuperLoop
|
||||||
|
${CPPUTEST_LIBRARIES}/libCppUTest.a
|
||||||
|
${CPPUTEST_LIBRARIES}/libCppUTestExt.a
|
||||||
|
SuperLoop
|
||||||
|
)
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
* Author: Jake G
|
||||||
|
* Date: 2024-09-01
|
||||||
|
* filename: test_SuperLoop.c
|
||||||
|
* description: module_purpose
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CppUTest/CommandLineTestRunner.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "SuperLoop.h"
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_GROUP(test_SuperLoop)
|
||||||
|
{
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void teardown()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TEST(test_SuperLoop, LoopIterationsFiniteWork){
|
||||||
|
for(uint8_t i = 1; i < 255; i++){
|
||||||
|
SuperLoop_SetIterations(i);
|
||||||
|
uint8_t num_iterations = SuperLoop_Run();
|
||||||
|
CHECK_EQUAL(i, num_iterations);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue