Compare commits

...

32 Commits
v0.1.2 ... main

Author SHA1 Message Date
jakeg00dwin b377eab7c0 Updated with comments on prescaler usage for F_CPU 2025-02-20 16:05:23 -08:00
jakeg00dwin 43d15247ad Updated version number from changes. 2025-02-20 15:55:34 -08:00
jakeg00dwin a29e16963f Merge branch 'dev' 2025-02-20 15:50:00 -08:00
jakeg00dwin d3d69ca180 Added linux include dir for AVR. 2025-02-20 15:46:12 -08:00
jakeg00dwin 05b6de17d0 Added new F_CPU define. 2025-02-20 15:45:55 -08:00
jakeg00dwin b2a3dcbed4 Added line for inclusion of AVR stuff on linux machines. 2025-02-20 15:45:44 -08:00
jakeg00dwin 49d8ca037b Adjusted file to use F_CPU after DIV8 and allow speed control during movement. 2025-02-20 15:45:29 -08:00
jakeg00dwin c2ed2cead0 Added fuse flashing commands for default 9.6MHz 2025-02-20 15:44:55 -08:00
jakeg00dwin 4d229a973c updated version number 2025-02-18 19:30:01 -08:00
jakeg00dwin cc57692a1d Updated the motor pulse define, too fast of a pulse doesn't wakeup the motor driver. 2025-02-18 19:29:30 -08:00
jakeg00dwin ba4b6f9f70 Updated version number. 2025-02-18 16:42:35 -08:00
jakeg00dwin 4dcfb1ea07 Setup speed control 2025-02-18 16:41:53 -08:00
jakeg00dwin 4adeec5219 Commented out unused link libs. 2025-02-18 16:41:42 -08:00
jakeg00dwin 17bd1a4e38 Added a define for the motor pulse timing, 1uS and 5uS both work well. 2025-02-18 16:41:31 -08:00
Jake Goodwin b21a8fbecf white space 2025-02-18 15:55:04 -08:00
Jake Goodwin 3f56d38e90 whitespace 2025-02-18 15:55:00 -08:00
Jake Goodwin d85616604f Added define for the correct header when using LSP 2025-02-17 18:33:51 -08:00
Jake Goodwin 28a5c50b23 Updated date 2025-02-17 18:33:32 -08:00
Jake Goodwin d455f80759 Updated date/username 2025-02-17 18:33:20 -08:00
Jake Goodwin 3aaf0a066e got ADC to pass current tests. 2025-02-16 17:34:20 -08:00
Jake Goodwin a5bb712789 Added expectations for setup.
- Commented out attiny404 expectations.
2025-02-16 15:02:19 -08:00
Jake Goodwin 9228d0703f Added attiny13a adc expectations. 2025-02-16 14:42:08 -08:00
Jake Goodwin 39ce0af7fb Added the missing test dir for SuperLoop 2025-02-16 10:30:39 -08:00
Jake Goodwin 3f2eb09427 Updated version number 0.2.0 --> 0.2.1
Commiting the version changes number.
2025-02-16 10:29:22 -08:00
Jake Goodwin de5cd13459 Added the template test files I made before.
+Mocking of ADC.
+Mocking of timer
+Mocking of Register editing.
+tests for all the above
2025-02-16 10:28:35 -08:00
Jake Goodwin a3d7307d96 Added def/define in main CMakeLists.txt
+ added def for UNIT_TESTING
2025-02-16 10:27:21 -08:00
Jake Goodwin 22c191363e Added mocks
+ ADC mocking.
+ Timer.
+ Register Editing.
2025-02-16 10:13:45 -08:00
jakeg00dwin b96945a2a5 updated version number and documentation 2025-02-14 14:12:03 -08:00
jakeg00dwin 2d65048f8e Added minimum acceptable speed. 2025-02-14 14:09:33 -08:00
jakeg00dwin bf39006dea Added the code to allow 0%-100% speed. 2025-02-14 14:06:52 -08:00
jakeg00dwin 71ff471fde changed function signiture to return uint8 type instead of uint16. 2025-02-14 14:02:13 -08:00
jakeg00dwin 724237147f changed `ReadADC()` into `ReadFader()`. Added `ReadSpeed()` function and documentation. 2025-02-14 13:57:52 -08:00
45 changed files with 1745 additions and 18 deletions

View File

@ -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)

View File

@ -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)

View File

@ -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)

71
inc/RegEdit.h Normal file
View File

@ -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

60
inc/config.h Normal file
View File

@ -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

View File

@ -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>
@ -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
@ -97,9 +104,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);
/** /**

View File

@ -1,4 +1,6 @@
add_subdirectory(MockRegEdit)
add_subdirectory(MockADC)
add_subdirectory(TimerMock)

View File

@ -0,0 +1,7 @@
add_library(MockADC STATIC
MockADC.c
)
target_include_directories(MockADC PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

84
mocks/MockADC/MockADC.c Normal file
View File

@ -0,0 +1,84 @@
/*
* 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_SetPin(uint8_t pin_num)
{
return;
}
void ADC_Setup(void)
{
is_setup = true;
return;
}
void ADC_Init(uint8_t pin_num)
{
mock_c()->actualCall("ADC_Init")
->withUnsignedIntParameters("pin_num", pin_num);
}
void ADC_Enable(void)
{
mock_c()->actualCall("ADC_Enable");
}
void ADC_Disable()
{
mock_c()->actualCall("ADC_Disable");
}
uint16_t ADC_ReadValue_Impl(uint8_t pin_num)
{
mock_c()->actualCall("ADC_ReadValue_Impl")
->withUnsignedIntParameters("pin_num", pin_num);
if(fake_index == 0){
return 0;
}
return fake_data[--fake_index];
}
uint16_t (*ADC_ReadValue)(uint8_t pin_num) = 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;
}

30
mocks/MockADC/MockADC.h Normal file
View File

@ -0,0 +1,30 @@
/**
* @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_SetPin(uint8_t pin_num);
void ADC_Init(uint8_t pin_num);
void ADC_Enable(void);
void ADC_Disable(void);
extern uint16_t (*ADC_ReadValue)(uint8_t pin_num);
void MockADC_PushValue(uint16_t value);
void MockADC_ZeroIndex(void);
int MockADC_GetIndex(void);
bool MockADC_IsSetup(void);
#endif //MOCKADC_H

View File

@ -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
)

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -0,0 +1,7 @@
add_library(TimerMock STATIC
TimerMock.c
)
target_include_directories(TimerMock PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

View File

@ -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);
}

View File

@ -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

97
src/ADC/ADC.c Normal file
View File

@ -0,0 +1,97 @@
/*
* 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_PIN_NUM 7
static bool IsInvalidPin(uint8_t pin_num) {
if (pin_num > MAX_PIN_NUM) {
return true;
}
return false;
}
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 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;
uint16_t adc_val = 0;
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;

68
src/ADC/ADC.h Normal file
View File

@ -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 <stdbool.h>
#include <stdint.h>
/**
* @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

17
src/ADC/CMakeLists.txt Normal file
View File

@ -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()

View File

@ -2,6 +2,11 @@ add_executable(${PROJECT_NAME}
main.c main.c
) )
target_link_libraries(${PROJECT_NAME}
RegEdit
#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 +36,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)

View File

@ -0,0 +1,7 @@
add_library(RegEdit STATIC
RegEdit.c
)
target_include_directories(RegEdit PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

53
src/RegEdit/RegEdit.c Normal file
View File

@ -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;
}

77
src/RegEdit/RegEdit.h Normal file
View File

@ -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

View File

@ -0,0 +1,7 @@
add_library(SuperLoop STATIC
SuperLoop.c
)
target_include_directories(SuperLoop PUBLIC
${CMAKE_CURRENT_LIST_DIR}
)

40
src/SuperLoop/SuperLoop.c Normal file
View File

@ -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;
}

29
src/SuperLoop/SuperLoop.h Normal file
View File

@ -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

View File

@ -1,8 +1,10 @@
#ifndef F_CPU #ifndef F_CPU
#define F_CPU 4800000UL #error "F_CPU not defined: defaulting to 9.6MHz"
#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>
@ -49,6 +51,7 @@ int main() {
while (1) { while (1) {
UpdateButtonOutput(&btn1); UpdateButtonOutput(&btn1);
UpdateButtonInput(&btn1); UpdateButtonInput(&btn1);
//MotorMoveTo(0);
} }
return 0; return 0;
@ -83,7 +86,26 @@ void InitProg(void) {
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
uint8_t val = (uint8_t)(ADC >> 2);
//Map the speed value to the 100%-50% duty cycle range.
//val = (uint8_t)( (float)val / 255.0 ) * 100;
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
@ -108,7 +130,7 @@ static inline uint8_t diff(uint8_t a, uint8_t b) {
} }
void MotorSetSavePos() { void MotorSetSavePos() {
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 *)ROM_SS1_ADR, pos);
return; return;
} }
@ -119,10 +141,13 @@ uint8_t MotorGetSavedPos(void) {
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);

17
src/timer/CMakeLists.txt Normal file
View File

@ -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()

75
src/timer/timer.c Normal file
View File

@ -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();
}

32
src/timer/timer.h Normal file
View File

@ -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

18
tests/ADC/CMakeLists.txt Normal file
View File

@ -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
)

204
tests/ADC/test_ADC.cpp Normal file
View File

@ -0,0 +1,204 @@
/*
* 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_InitPortbADC3UsesCorrectRegisters)
{
//PB3/ADC3
//Check it disables the pin's digital circuitry
//Check that the ADC pin is selected in ADMUX
//
/*
//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);
}

View File

@ -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)

View File

@ -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
)

View File

@ -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
)

View File

@ -0,0 +1,94 @@
/*
* 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("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());
}

View File

@ -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
)

View File

@ -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();
}

13
tests/MockTests.cpp Normal file
View File

@ -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

View File

@ -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
)

View File

@ -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);
}

View File

@ -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
)

View File

@ -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);
}
}