Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "External/MockTools"]
path = External/MockTools
url = https://github.com/ToolboxPlane/MockTools.git
3 changes: 3 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
project(AvrHAL)
add_library(${PROJECT_NAME} STATIC adc.c i2c.c pwm16bit.c spi.c timer8bit.c uart.c)

add_subdirectory(External/MockTools)
add_subdirectory(Tests)
1 change: 1 addition & 0 deletions External/MockTools
Submodule MockTools added at 7b5afe
12 changes: 12 additions & 0 deletions Tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
make_test(MODULE_UNDER_TEST ../pwm16bit.c
TEST_DEFINITION pwm16bit.cpp
REQUIRED_HEADERS
${MockLib_SOURCE_DIR}/../System/avr/io.h)
make_test(MODULE_UNDER_TEST ../timer8bit.c
TEST_DEFINITION timer8bit.cpp
REQUIRED_HEADERS
${MockLib_SOURCE_DIR}/../System/avr/io.h)
make_test(MODULE_UNDER_TEST ../uart.c
TEST_DEFINITION uart.cpp
REQUIRED_HEADERS
${MockLib_SOURCE_DIR}/../System/avr/io.h)
410 changes: 410 additions & 0 deletions Tests/pwm16bit.cpp

Large diffs are not rendered by default.

265 changes: 265 additions & 0 deletions Tests/timer8bit.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
#include <gtest/gtest.h>
#include <Mock/io.hpp>

extern "C" {
#include <HAL/timer8bit.h>
#include <System/avr/interrupt.h>
}

bool callbackCalled = false;
void callback() {
callbackCalled = true;
}


TEST(TEST_NAME, init__timer_0_no_clock) {
timer_8bit_init(TIMER_ID_0, no_clock, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 0); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_prescaler_1) {
timer_8bit_init(TIMER_ID_0, prescaler_1, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 1); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_prescaler_8) {
timer_8bit_init(TIMER_ID_0, prescaler_8, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 2); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_prescaler_64) {
timer_8bit_init(TIMER_ID_0, prescaler_64, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 3); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_prescaler_256) {
timer_8bit_init(TIMER_ID_0, prescaler_256, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 4); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_prescaler_1024) {
timer_8bit_init(TIMER_ID_0, prescaler_1024, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 5); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_prescaler_clock_falling) {
timer_8bit_init(TIMER_ID_0, external_falling, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 6); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_prescaler_clock_rising) {
timer_8bit_init(TIMER_ID_0, external_rising, nullptr);

EXPECT_EQ((TCCR0A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR0A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR0B >> 1U) & (0b100U)) | (TCCR0A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR0B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR0B & 0b111U), 7); // CS
EXPECT_EQ(TCNT0, 0);
EXPECT_EQ(TIMSK0, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_0_callback) {
timer_8bit_init(TIMER_ID_0, no_clock, callback);
callbackCalled = false;
TIMER0_OVF_vect();
EXPECT_TRUE(callbackCalled);
}

TEST(TEST_NAME, init__timer_2_no_clock) {
timer_8bit_init(TIMER_ID_2, no_clock, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 0); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_prescaler_1) {
timer_8bit_init(TIMER_ID_2, prescaler_1, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 1); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_prescaler_8) {
timer_8bit_init(TIMER_ID_2, prescaler_8, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 2); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_prescaler_32) {
timer_8bit_init(TIMER_ID_2, prescaler_32, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 3); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_prescaler_64) {
timer_8bit_init(TIMER_ID_2, prescaler_64, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 4); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_prescaler_128) {
timer_8bit_init(TIMER_ID_2, prescaler_128, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 5); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_prescaler_256) {
timer_8bit_init(TIMER_ID_2, prescaler_256, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 6); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_prescaler_1024) {
timer_8bit_init(TIMER_ID_2, prescaler_1024, nullptr);

EXPECT_EQ((TCCR2A >> 6U) & 0b11U, 0); //COMnA
EXPECT_EQ((TCCR2A >> 4U) & 0b11U, 0); //COMnB
EXPECT_EQ(((TCCR2B >> 1U) & (0b100U)) | (TCCR2A & 0b11U), 0); // WGMn
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnA
EXPECT_EQ((TCCR2B >> 7U) & 0b1U, 0); //FOCnB
EXPECT_EQ((TCCR2B & 0b111U), 7); // CS
EXPECT_EQ(TCNT2, 0);
EXPECT_EQ(TIMSK2, 0b00000001); // Interrupts: only OV
}

TEST(TEST_NAME, init__timer_2_callback) {
timer_8bit_init(TIMER_ID_2, no_clock, callback);
callbackCalled = false;
TIMER2_OVF_vect();
EXPECT_TRUE(callbackCalled);
}

TEST(TEST_NAME, get__timer_0_0) {
TCNT0 = 0;
EXPECT_EQ(timer_8bit_get_count(TIMER_ID_0), 0);
}

TEST(TEST_NAME, get__timer_0_17) {
TCNT0 = 17;
EXPECT_EQ(timer_8bit_get_count(TIMER_ID_0), 17);
}

TEST(TEST_NAME, get__timer_0_255) {
TCNT0 = 255;
EXPECT_EQ(timer_8bit_get_count(TIMER_ID_0), 255);
}

TEST(TEST_NAME, get__timer_2_0) {
TCNT2 = 0;
EXPECT_EQ(timer_8bit_get_count(TIMER_ID_2), 0);
}

TEST(TEST_NAME, get__timer_2_17) {
TCNT2 = 17;
EXPECT_EQ(timer_8bit_get_count(TIMER_ID_2), 17);
}

TEST(TEST_NAME, get__timer_2_255) {
TCNT2 = 255;
EXPECT_EQ(timer_8bit_get_count(TIMER_ID_2), 255);
}
10 changes: 10 additions & 0 deletions Tests/uart.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#include <gtest/gtest.h>
#include <Mock/io.hpp>

extern "C" {
#include <HAL/uart.h>
}

TEST(TEST_NAME, test) {

}
35 changes: 31 additions & 4 deletions pwm16bit.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,56 @@ typedef enum {
} pwm_clock_option_t;

/**
* Initialize, enable and start the pwm
* @brief Initialize, enable and start the pwm
*
* For the initialization the following register settings are used (for the corresponding timer id):
* * Timer/Counter Control Register A:
* * Waveform Generation: Fast PWM with ICRn as top (mode 14), see Table 17.2
* * Compare Output mode: non inverting mode (mode 2), see Table 17.4
* * Timer/Counter Control Register B:
* * Input Capture Noise Canceller: disabled, as no input is captured
* * Input Capture Edge Select: disabled, as no input is captured
* * Waveform Generation: see TCCA
* * Clock Select: according to parameter pwm_clock_option
* * Timer/Counter Control Register C:
* * Force Output compare: disabled as PWM is active
* * Timer/Counter: initialized to 0
* * Output Compare Registers: initialized to 0
* * Input Capture Registers: defines the top in PWM mode, set to parameter "top"
* * Timer/Counter Interrupt Mask Register: All interrupt disabled
* * Timer/Counter Interrupt Flag Registers: not applicable as interrupts are disabled
*
* @param timer_id the number of the timer, should be in {1,3,4,5}
* @param pwm_clock_option a value of pwm_clock_option_t to select the prescaler
* @param top the maximum value of the counter, should be in [1,65535]
*/
void pwm_init(uint8_t timer_id, pwm_clock_option_t pwm_clock_option, uint16_t top);

/**
* Set the pwm1 output a to specifiy duty cycle (relative to top)
* @brief Set the PWM output a (OCnA) to specific duty cycle (relative to top)
*
* To set the duty cycle the parameter "val" is written to the respective Output Compare Register A
*
* @param timer_id the number of the timer, should be in {1,3,4,5}
* @param val the compare value, the duty cycle is given by val/top
*/
void pwm_set_out_a(uint8_t timer_id, uint16_t val);

/**
* Set the pwm1 output b to specifiy duty cycle (relative to top)
* @brief Set the PWM output b (OCnB) to specific duty cycle (relative to top)
*
* To set the duty cycle the parameter "val" is written to the respective Output Compare Register B
*
* @param timer_id the number of the timer, should be in {1,3,4,5}
* @param val the compare value, the duty cycle is given by val/top
*/
void pwm_set_out_b(uint8_t timer_id, uint16_t val);

/**
* Set the pwm1 output c to specifiy duty cycle (relative to top)
* @brief Set the PWM output c (OCnC) to specific duty cycle (relative to top)
*
* To set the duty cycle the parameter "val" is written to the respective Output Compare Register C
*
* @param timer_id the number of the timer, should be in {1,3,4,5}
* @param val the compare value, the duty cycle is given by val/top
*/
Expand Down
6 changes: 3 additions & 3 deletions timer8bit.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,10 +62,10 @@ ISR(TIMER2_OVF_vect) {
void timer_8bit_init(timer_8bit_id_t num, timer_8bit_clock_option_t timer_clock_option,
timer_8bit_callback_t callback) {
instances[num].callback = callback;
*instances[num].tccra = 0b00000000u; // Output compare disconnected, normal mode
*instances[num].tccra = 0b00000000U; // Output compare disconnected, normal mode
*instances[num].tccrb =
0b00000000u | prescaler_bits[num][timer_clock_option]; // No force override, normal mode, prescaler
*instances[num].timsk = 0b00000001u; // Overflow interrupt enabled
0b00000000U | prescaler_bits[num][timer_clock_option]; // No force override, normal mode, prescaler
*instances[num].timsk = 0b00000001U; // Overflow interrupt enabled

*instances[num].tcnt = 0; // Set the counter to 0
}
Expand Down
Loading