Skip to content

Commit d95437d

Browse files
committed
Merge branch 'main' into hsv
2 parents 8148361 + 336e2c4 commit d95437d

18 files changed

+770
-36
lines changed

tests/lockfree_fifo_spsc_tests.cc

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,39 @@ TEST_CASE("Construct with offset") {
132132
a.put(6);
133133
CHECK(a.get().value() == 4);
134134
}
135+
136+
TEST_CASE("num_free") {
137+
LockFreeFifoSpsc<int, 4> a;
138+
139+
CHECK(a.num_free() == 4);
140+
a.put(1);
141+
CHECK(a.num_free() == 3);
142+
a.put(2);
143+
CHECK(a.num_free() == 2);
144+
a.put(3);
145+
CHECK(a.num_free() == 1);
146+
a.put(4);
147+
CHECK(a.num_free() == 0);
148+
CHECK(a.put(5) == false);
149+
CHECK(a.num_free() == 0);
150+
151+
a.get();
152+
CHECK(a.num_free() == 1);
153+
a.put(6);
154+
CHECK(a.num_free() == 0);
155+
a.get();
156+
CHECK(a.num_free() == 1);
157+
a.get();
158+
CHECK(a.num_free() == 2);
159+
a.get();
160+
CHECK(a.num_free() == 3);
161+
a.get();
162+
CHECK(a.num_free() == 4);
163+
a.get();
164+
CHECK(a.num_free() == 4);
165+
166+
a.put(7);
167+
CHECK(a.num_free() == 3);
168+
a.put(8);
169+
CHECK(a.num_free() == 2);
170+
}

tests/schmitt_trigger_tests.cc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#include "doctest.h"
2+
#include "util/schmitt_trigger.hh"
3+
4+
TEST_CASE("basic usage") {
5+
cpputil::SchmittTrigger t;
6+
7+
t.process(0.3f);
8+
CHECK(t.is_high() == false);
9+
CHECK(t.just_went_high() == false);
10+
CHECK(t.just_went_low() == false);
11+
12+
t.process(0.5f);
13+
CHECK(t.is_high() == false);
14+
CHECK(t.just_went_high() == false);
15+
CHECK(t.just_went_low() == false);
16+
17+
t.process(0.6f);
18+
CHECK(t.is_high() == false);
19+
CHECK(t.just_went_high() == false);
20+
CHECK(t.just_went_low() == false);
21+
22+
t.process(0.61f);
23+
CHECK(t.is_high() == true);
24+
CHECK(t.just_went_high() == true);
25+
CHECK(t.just_went_low() == false);
26+
27+
// state clears after reading it
28+
CHECK(t.just_went_high() == false);
29+
30+
t.process(0.7f);
31+
CHECK(t.is_high() == true);
32+
CHECK(t.just_went_high() == false);
33+
CHECK(t.just_went_low() == false);
34+
35+
t.process(0.6f);
36+
CHECK(t.is_high() == true);
37+
CHECK(t.just_went_high() == false);
38+
CHECK(t.just_went_low() == false);
39+
40+
t.process(0.5f);
41+
CHECK(t.is_high() == true);
42+
CHECK(t.just_went_high() == false);
43+
CHECK(t.just_went_low() == false);
44+
45+
t.process(0.4f);
46+
CHECK(t.is_high() == true);
47+
CHECK(t.just_went_high() == false);
48+
CHECK(t.just_went_low() == false);
49+
50+
t.process(0.39f);
51+
CHECK(t.is_high() == false);
52+
CHECK(t.just_went_high() == false);
53+
CHECK(t.just_went_low() == true);
54+
55+
// state clears after reading it
56+
CHECK(t.just_went_low() == false);
57+
}

tests/sequential_map_tests.cc

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include "doctest.h"
2+
#include "util/sequential_map.hh"
3+
4+
TEST_CASE("Basic use") {
5+
6+
SequentialMap<int, float, 4> sm;
7+
8+
// Pre-conditions:
9+
CHECK(sm.size() == 0);
10+
CHECK(sm.is_full() == false);
11+
12+
// Add a value
13+
sm[2] = 3.f;
14+
CHECK(sm.size() == 1);
15+
CHECK(sm.is_full() == false);
16+
CHECK(sm.contains(2));
17+
CHECK(sm[2] == 3.f);
18+
19+
sm[9] = 99.f;
20+
CHECK(sm.size() == 2);
21+
CHECK(sm.is_full() == false);
22+
CHECK(sm.contains(9));
23+
CHECK(sm[9] == 99.f);
24+
25+
// Change a value
26+
sm[2] = 5.f;
27+
CHECK(sm.size() == 2);
28+
CHECK(sm.is_full() == false);
29+
CHECK(sm.contains(2));
30+
CHECK(sm[2] == 5.f);
31+
32+
// Fill it up
33+
sm[20] = 20.20f;
34+
CHECK(sm.size() == 3);
35+
CHECK(sm.is_full() == false);
36+
37+
sm[30] = 30.30f;
38+
CHECK(sm.size() == 4);
39+
CHECK(sm.is_full() == true);
40+
41+
// Overflow is handled by overwriting the last value added
42+
CHECK(sm.contains(30));
43+
sm[99] = 10.010f;
44+
CHECK_FALSE(sm.contains(30));
45+
CHECK(sm.contains(99));
46+
}
47+
48+
TEST_CASE("Erase") {
49+
SequentialMap<char, unsigned, 4> sm;
50+
51+
sm['a'] = 1;
52+
sm['b'] = 10;
53+
sm['c'] = 100;
54+
sm['d'] = 1000;
55+
56+
auto it_b = sm.find('b');
57+
58+
SUBCASE("Erase first") {
59+
CHECK(sm.erase('a') == 1);
60+
CHECK(sm.size() == 3);
61+
CHECK(sm.contains('a') == false);
62+
CHECK(sm.contains('b') == true);
63+
CHECK(sm.contains('c') == true);
64+
CHECK(sm.contains('d') == true);
65+
66+
// Iterator is now invalid!
67+
// This breaks with std::map
68+
CHECK_FALSE(it_b->first == 'b');
69+
CHECK_FALSE(it_b->second == 10);
70+
}
71+
72+
SUBCASE("Erase middle") {
73+
CHECK(sm.erase('b') == 1);
74+
CHECK(sm.size() == 3);
75+
CHECK(sm.contains('a') == true);
76+
CHECK(sm.contains('b') == false);
77+
CHECK(sm.contains('c') == true);
78+
CHECK(sm.contains('d') == true);
79+
}
80+
81+
SUBCASE("Erase last") {
82+
CHECK(sm.erase('d') == 1);
83+
CHECK(sm.size() == 3);
84+
CHECK(sm.contains('a') == true);
85+
CHECK(sm.contains('b') == true);
86+
CHECK(sm.contains('c') == true);
87+
CHECK(sm.contains('d') == false);
88+
89+
// Iterator is still valid
90+
CHECK(it_b->first == 'b');
91+
CHECK(it_b->second == 10);
92+
}
93+
94+
// Can still add a new one
95+
sm['e'] = 10000;
96+
CHECK(sm.contains('e'));
97+
CHECK(sm['e'] == 10000);
98+
}

util/aligned_allocator.hh

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <cstddef>
2+
#include <cstdlib>
3+
4+
template<typename T, std::size_t Alignment = 64>
5+
class AlignedAllocator {
6+
public:
7+
using value_type = T;
8+
9+
AlignedAllocator() noexcept = default;
10+
11+
template<typename U>
12+
AlignedAllocator(const AlignedAllocator<U, Alignment> &) noexcept {
13+
}
14+
15+
T *allocate(std::size_t n) {
16+
if (n == 0)
17+
return nullptr;
18+
19+
std::size_t size = n * sizeof(T);
20+
std::size_t aligned_size = ((size + Alignment - 1) / Alignment) * Alignment;
21+
22+
void *ptr = aligned_alloc(Alignment, aligned_size);
23+
if (!ptr)
24+
return nullptr;
25+
26+
return static_cast<T *>(ptr);
27+
}
28+
29+
void deallocate(T *p, std::size_t) noexcept {
30+
std::free(p);
31+
}
32+
33+
template<typename U>
34+
struct rebind {
35+
using other = AlignedAllocator<U, Alignment>;
36+
};
37+
38+
bool operator==(const AlignedAllocator &) const noexcept {
39+
return true;
40+
}
41+
bool operator!=(const AlignedAllocator &) const noexcept {
42+
return false;
43+
}
44+
};

util/callable.hh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,19 @@ private:
7676
template<typename Signature>
7777
using Function = FunctionSized<sizeof(void *) * 2, Signature>;
7878

79+
7980
template<unsigned size = sizeof(void *) * 2>
80-
using CallbackSized = FunctionSized<size, void(void)>;
81+
struct CallbackSized : FunctionSized<size, void(void)>{
82+
CallbackSized() = default;
83+
84+
template<typename Callable>
85+
CallbackSized(Callable callable) : FunctionSized<size, void(void)>{callable}{}
86+
87+
};
88+
// Note: we could just define CallbackSized like the following, but
89+
// that breaks the API for functions using CallbackSized in their signature
90+
// template<unsigned size = sizeof(void *) * 2>
91+
// using CallbackSized = FunctionSized<size, void(void)>;
8192

8293
using Callback = CallbackSized<2 * sizeof(void *)>;
94+

util/colors_rgb565.hh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,12 @@ struct RGB565 {
3939
}
4040

4141
//0..255
42-
constexpr uint8_t green() {
42+
constexpr uint8_t green() const {
4343
return (raw() & 0x07e0) >> 3;
4444
}
4545

4646
//0..255
47-
constexpr uint8_t blue() {
47+
constexpr uint8_t blue() const {
4848
return (raw() & 0x001f) << 3;
4949
}
5050
};

util/debouncer.hh

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ public:
7272
got_rising_edge_ = false;
7373
}
7474

75+
void process(bool newstate) {
76+
register_state(newstate);
77+
}
78+
7579
void register_state(bool newstate) {
7680
if (newstate == is_high_)
7781
return;

util/edge_detector.hh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,18 @@ class RisingEdgeDetector {
4444

4545
public:
4646
bool update(bool state) {
47-
const auto out = state && last_state_ != state;
47+
const auto out = state && (last_state_ != state);
48+
last_state_ = state;
49+
return out;
50+
}
51+
};
52+
53+
class FallingEdgeDetector {
54+
bool last_state_ = false;
55+
56+
public:
57+
bool update(bool state) {
58+
const auto out = !state && (last_state_ != state);
4859
last_state_ = state;
4960
return out;
5061
}

util/fixed_vector.hh

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <array>
44
#include <cstddef>
55
#include <iterator>
6+
#include <span>
67

78
template<typename T, size_t MaxElements>
89
class FixedVector {
@@ -34,6 +35,25 @@ public:
3435
return true;
3536
}
3637

38+
// Resizes
39+
bool resize(size_t num, T el = T{}) {
40+
const auto new_back_idx = std::min(num, MaxElements);
41+
42+
if (new_back_idx > back_idx) {
43+
for (auto i = back_idx; i < new_back_idx; i++) {
44+
data[i] = el;
45+
}
46+
}
47+
48+
back_idx = new_back_idx;
49+
return (num == new_back_idx);
50+
}
51+
52+
bool resize_for_overwrite(size_t num) {
53+
back_idx = std::min(num, MaxElements);
54+
return (num == back_idx);
55+
}
56+
3757
// returns MaxElements for failure
3858
size_t push_back_for_overwrite() {
3959
if (back_idx >= MaxElements)
@@ -57,7 +77,7 @@ public:
5777
return back_idx;
5878
}
5979

60-
constexpr size_t max_size() {
80+
constexpr size_t max_size() const {
6181
return MaxElements;
6282
}
6383

@@ -109,6 +129,8 @@ public:
109129
back_idx -= count;
110130
}
111131

132+
using iterator = typename decltype(data)::iterator;
133+
112134
auto begin() const {
113135
return data.begin();
114136
}
@@ -124,4 +146,12 @@ public:
124146
auto end() {
125147
return begin() + back_idx;
126148
}
149+
150+
auto span() {
151+
return std::span{begin(), back_idx};
152+
}
153+
154+
auto span() const {
155+
return std::span{begin(), back_idx};
156+
}
127157
};

0 commit comments

Comments
 (0)