テスト用のあれこれ共用フォルダ
Revision | f85ea7093d3d70ee3e9b6e57f24536a7ee5a7fd6 (tree) |
---|---|
Time | 2018-02-28 07:29:39 |
Author | takemasa <suikan@user...> |
Commiter | takemasa |
Implemented BaseFIFO
@@ -12,8 +12,8 @@ | ||
12 | 12 | <targetDefinitions> |
13 | 13 | <board id="nucleo-f746zg"> |
14 | 14 | <name>NUCLEO-F746ZG</name> |
15 | - <dbgIF>SWD</dbgIF> | |
16 | 15 | <dbgIF>JTAG</dbgIF> |
16 | + <dbgIF>SWD</dbgIF> | |
17 | 17 | <dbgDEV>ST-Link</dbgDEV> |
18 | 18 | <mcuId>stm32f746zgtx</mcuId> |
19 | 19 | </board> |
@@ -6,18 +6,104 @@ | ||
6 | 6 | */ |
7 | 7 | |
8 | 8 | #include <basefifo.hpp> |
9 | +#include <murasaki_assert.hpp> | |
10 | +#include <algorithm> | |
11 | +#include <string.h> | |
9 | 12 | |
10 | 13 | namespace murasaki { |
11 | 14 | |
12 | -BaseFifo::BaseFifo() | |
15 | +BaseFifo::BaseFifo(unsigned int buffer_size): | |
16 | + size_of_buffer_(buffer_size), | |
17 | + buffer_(new uint8_t[size_of_buffer_]) | |
13 | 18 | { |
14 | - // TODO Auto-generated constructor stub | |
19 | + MURASAKI_ASSERT(size_of_buffer_ != 0); // very explicit check | |
20 | + MURASAKI_ASSERT(buffer_ != nullptr); | |
15 | 21 | |
16 | 22 | } |
17 | 23 | |
24 | + | |
18 | 25 | BaseFifo::~BaseFifo() |
19 | 26 | { |
20 | - // TODO Auto-generated destructor stub | |
27 | + if (buffer_ != nullptr) | |
28 | + delete[] buffer_; | |
29 | +} | |
30 | + | |
31 | +unsigned int BaseFifo::Put(uint8_t const data[], unsigned int size) | |
32 | +{ | |
33 | + unsigned int avairable; | |
34 | + | |
35 | + // check the avairable area size. Data is append to the head | |
36 | + if (head_ > tail_) // there is no wrap around | |
37 | + avairable = size_of_buffer_ - (head_ - tail_); | |
38 | + else if (tail_ > head_) | |
39 | + avairable = tail_ - head_; | |
40 | + else | |
41 | + avairable = size_of_buffer_; | |
42 | + | |
43 | + // If we fill up buffer entirely, we can not distinguish full and empty from the | |
44 | + // comparing tail_ and head_. | |
45 | + // This can be fixed if we add new variable "length", but it get complex. | |
46 | + // To save this problem, we clip the vacant size by buffsersize-1. | |
47 | + if (avairable > 0) | |
48 | + avairable--; | |
49 | + | |
50 | + // clip the line size by available room in the buffer. | |
51 | + unsigned int copy_size = std::min(size, avairable); | |
52 | + | |
53 | + // Now, we can copy from line to buffer. | |
54 | + for (unsigned int i = 0; i < copy_size; i++) { | |
55 | + // newest data is appended to the point of head_ | |
56 | + buffer_[head_] = data[i]; | |
57 | + head_++; | |
58 | + | |
59 | + // wrap around the head index; | |
60 | + if (head_ >= size_of_buffer_) | |
61 | + head_ = 0; | |
62 | + } // end for loop. | |
63 | + | |
64 | + return copy_size; | |
65 | + | |
66 | +} | |
67 | + | |
68 | +unsigned int BaseFifo::Get(uint8_t data[], unsigned int size) | |
69 | +{ | |
70 | + unsigned int copy_size = 0; | |
71 | + | |
72 | + // To avoid race condition, Take a snapshot of the head_ and tail_ pointer. | |
73 | + // head_ could be modified during this task is running but no problem. | |
74 | + // check whether the data area is wrapped araound at the end of buffer. Note : Data is added to the head. | |
75 | + | |
76 | + if (head_ == tail_) | |
77 | + copy_size = 0; // nothing to copy | |
78 | + else { | |
79 | + if (head_ > tail_) | |
80 | + copy_size = std::min(size, head_ - tail_); | |
81 | + else | |
82 | + // tail_ > head_ | |
83 | + copy_size = std::min(size, size_of_buffer_ - tail_); // stop once, at the end of buffer. | |
84 | + | |
85 | + // copy data to output buffer | |
86 | + ::memcpy(data, &buffer_[tail_], copy_size); | |
87 | + // update tail. | |
88 | + tail_ += copy_size; | |
89 | + | |
90 | + // if tail_ reaches the end, wrap around. | |
91 | + if (tail_ >= size_of_buffer_) | |
92 | + tail_ = 0; | |
93 | + } | |
94 | + | |
95 | + | |
96 | + return copy_size; | |
97 | +} | |
98 | + | |
99 | +void BaseFifo::ReWind() | |
100 | +{ | |
101 | + // by setting tail as head+1, the entire buffer is marked as "not sent" | |
102 | + tail_ = head_ + 1; | |
103 | + | |
104 | + // wrap arround; | |
105 | + if (tail_ >= size_of_buffer_) | |
106 | + tail_ = 0; | |
21 | 107 | } |
22 | 108 | |
23 | 109 | } /* namespace murasaki */ |
@@ -1,28 +1,81 @@ | ||
1 | -/* | |
2 | - * basefifo.hpp | |
1 | +/** | |
2 | + * @file basefifo.hpp | |
3 | 3 | * |
4 | - * Created on: 2018/02/26 | |
5 | - * Author: takemasa | |
4 | + * @date 2018/02/26 | |
5 | + * @author takemasa | |
6 | 6 | */ |
7 | 7 | |
8 | 8 | #ifndef BASEFIFO_HPP_ |
9 | 9 | #define BASEFIFO_HPP_ |
10 | 10 | |
11 | 11 | #include <ctype.h> |
12 | +#include <cinttypes> | |
12 | 13 | |
13 | 14 | namespace murasaki { |
14 | 15 | |
16 | +/** | |
17 | + * @brief Basic FIFO without thread safe. | |
18 | + * @details | |
19 | + * Foundemental FIFO. No blocking , not thread safe. | |
20 | + * | |
21 | + * The Put member function returns with "copied" data count. | |
22 | + * If the internal buffer is full, it returns without copy data. | |
23 | + * | |
24 | + * The Get member funciton returns with "copied" data count and data. | |
25 | + * If the internal buffer is empty, it returns without copy data. | |
26 | + * | |
27 | + */ | |
15 | 28 | class BaseFifo |
16 | 29 | { |
17 | 30 | public: |
31 | + BaseFifo() = delete; | |
32 | + /** | |
33 | + * @brief Create an internal buffer | |
34 | + * @param buffer_size Size of the internal buffer to be allocated [byte] | |
35 | + * @details | |
36 | + * Allocate the internal buffer with given buffer_size. | |
37 | + */ | |
18 | 38 | BaseFifo(unsigned int buffer_size); |
39 | + /** | |
40 | + * @breif Delete an internal buffer | |
41 | + */ | |
19 | 42 | virtual ~BaseFifo(); |
43 | + /** | |
44 | + * @brief Put the data into the internal buffer. | |
45 | + * @param data Data to be copied to the internal buffer | |
46 | + * @param size Data count to be copied | |
47 | + * @return The count of copied data. 0, if the internal buffer is full. | |
48 | + */ | |
20 | 49 | unsigned int Put(uint8_t const data[], unsigned int size); |
50 | + /** | |
51 | + * @brief Get the data from the internal buffer. | |
52 | + * @param data Data buffer to receive from the internal buffer | |
53 | + * @param size Size of the data parameter. | |
54 | + * @return The count of copied data. 0, if the internal buffer is empty | |
55 | + */ | |
21 | 56 | unsigned int Get(uint8_t data[], unsigned int size); |
57 | + /* | |
58 | + * @brief Mark all the data inside the internal buffer as "not sent". | |
59 | + */ | |
22 | 60 | void ReWind(); |
23 | 61 | private: |
62 | + /** | |
63 | + * @brief The index of where next data will be written. | |
64 | + */ | |
24 | 65 | unsigned int head_ = 0; |
66 | + /** | |
67 | + * @brief The index of where the next data will be read. | |
68 | + * @details | |
69 | + * If head_ = tail_, buffer is empty. | |
70 | + */ | |
25 | 71 | unsigned int tail_ = 0; |
72 | + /** | |
73 | + * @brief Size of the internal buffer [byte] | |
74 | + */ | |
75 | + unsigned int const size_of_buffer_; | |
76 | + /** | |
77 | + * @brief The internal buffer. Allocated by constructor. | |
78 | + */ | |
26 | 79 | uint8_t * const buffer_; |
27 | 80 | |
28 | 81 | }; |