Skip to content

Commit 585f998

Browse files
committed
Touched up documentation, added example
1 parent 9345d25 commit 585f998

File tree

7 files changed

+327
-3
lines changed

7 files changed

+327
-3
lines changed

Adafruit_RA8875_Due.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ typedef volatile union _SADDR_Type {
1111
Word raw;
1212
} SADDR_Type;
1313

14+
/**
15+
* Redef of the LLI as an entry in a row.
16+
* Uses SADDR_Type union for easier debugging of what's in the SADDR field
17+
*/
1418
typedef volatile struct _RowFrame {
1519
SADDR_Type SADDR;
1620
Word DADDR;
@@ -30,6 +34,12 @@ typedef volatile struct _Row {
3034
}
3135
} Row;
3236

37+
/**
38+
* Gets a chunk of LLIs and treats them like an entire row of pixels. Good for bulk operations
39+
* @param manager The DMA Manager
40+
* @param row Which row to get
41+
* @return The collection of frames as a row pointer, if within range. Nullptr otherwise
42+
*/
3343
static Row *get_row(DMAManager *manager, size_t row) {
3444
if (row * FRAMES_PER_LINE >= LLI_MAX_FRAMES) {
3545
return nullptr;

DMAManager.h

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,33 @@
1111
* */
1212
/********************************/
1313
#ifndef FRAMES_PER_LINE
14+
/**
15+
* The number of frames required to draw one line to the screen.
16+
*/
1417
#define FRAMES_PER_LINE 16
1518
#endif
1619
#ifndef LINES_PER_DMA
20+
/**
21+
* The number of lines to be created/filled before the transfer starts
22+
*/
1723
#define LINES_PER_DMA 8
1824
#endif
1925
#ifndef WORKING_DATA_PER_LINE
26+
/**
27+
* The number of bytes required to draw a line on the screen
28+
*/
2029
#define WORKING_DATA_PER_LINE 19
2130
#endif
2231

2332
#define LLI_MAX_FRAMES (FRAMES_PER_LINE * LINES_PER_DMA)
2433
#define WORKING_DATA_SIZE (WORKING_DATA_PER_LINE * LINES_PER_DMA)
34+
/**
35+
* The number of bytes needed to set the lower/upper bytes for one coordinate
36+
*/
2537
#define COORD_BUF_SPACE 4
38+
/**
39+
* How long to wait / buffer the CS pin low or high
40+
*/
2641
#define DMA_CS_HIGH_TRANSFERS 8
2742

2843
// Forward Declaration for class
@@ -66,8 +81,14 @@ typedef union DMAFunctionData {
6681
} DMAFunctionData;
6782

6883
typedef struct DMACallbackData {
84+
/**
85+
* Data for use in the complete_cb function
86+
*/
6987
void *dataPtr;
7088

89+
/**
90+
* Function called when transfers are complete
91+
*/
7192
void (*complete_cb)(void *);
7293
} DMACallbackData;
7394

@@ -98,12 +119,19 @@ typedef struct DMA_Data {
98119

99120
void volatile (*on_complete)(SpiDriver *spiDriver);
100121

101-
122+
/**
123+
* Resets the working data idx to 0. Doesn't actually clear data, just allows for overwrite
124+
* @param full_clear Resets last_idx if true
125+
*/
102126
inline void clear_working_data(bool full_clear = false) {
103127
last_storage_idx = full_clear ? 0 : storage_idx;
104128
storage_idx = 0;
105129
}
106130

131+
/**
132+
* Completely resets the DMA_Data instance
133+
* @param full_reset Clears the last_data fields
134+
*/
107135
inline void reset(bool full_reset = false) {
108136
clear_working_data(full_reset);
109137
memset_volatile(&functionData, '\0', sizeof(DMAFunctionData));
@@ -116,10 +144,21 @@ typedef struct DMA_Data {
116144
on_complete = nullptr;
117145
}
118146

147+
/**
148+
* @param size The amount of bytes needed to add
149+
* @return true if there is space to add, false otherwise
150+
*/
119151
inline bool can_add_working_data(size_t size) const {
120152
return ((storage_idx - 1) + size) < WORKING_DATA_SIZE;
121153
}
122154

155+
/**
156+
* Store sensitive data needed for DMA in a buffer for use during the transfers.
157+
* Provides a size check to make sure the data can be added.
158+
* @param buf The data to store
159+
* @param size The number of bytes being added.
160+
* @return uint8_t ptr to the location of the added data in the permanent buffer for future access.
161+
*/
123162
inline volatile uint8_t *add_working_data(const uint8_t *buf, size_t size) {
124163
if (!can_add_working_data(size)) {
125164
return nullptr;
@@ -165,6 +204,12 @@ class DMAManager {
165204

166205
volatile LLI *get_next_blank_entry();
167206

207+
/**
208+
* Gets an entry from the chain
209+
* @param idx The idx to get.
210+
* @param force If the index is out of 'size' bounds, will return nullptr unless force is true. Will return the index from the array
211+
* @return The entry, if within range (or if force specified). Nullptr otherwise.
212+
*/
168213
volatile LLI *get_entry(size_t idx, bool force = false);
169214

170215
inline volatile LLI *get_last() {
@@ -179,16 +224,28 @@ class DMAManager {
179224
* until we're done with the entire chain. This way if an element needs to be removed, all the `next` pointers won't need to be
180225
* rewritten.
181226
* This must be called before passing the beginning entry to DMA
227+
* @return Ptr to the head of the list
182228
*/
183229
volatile LLI *finalize();
184230

231+
/**
232+
* Resets the size counter, does not zero memory
233+
*/
185234
void clear_frames();
186235

236+
/**
237+
* Resets frames & working data
238+
* @param full Clears the 'last_data' fields, if true
239+
*/
187240
void reset(bool full = false);
188241

189242
size_t get_size() const;
190243

191-
bool can_add_entries(uint32_t entries) const;
244+
/**
245+
* @param entries The number of entries to check if available
246+
* @return True if space, false otherwise
247+
*/
248+
bool can_add_entries(size_t entries) const;
192249

193250
DMA_Data *get_cur_data() {
194251
return &transaction_data;
@@ -197,18 +254,55 @@ class DMAManager {
197254
/************************
198255
* General purpose methods for adding SPI Frames, PIO Frames, etc.
199256
************************/
257+
258+
/**
259+
* @param state The state of the pin (Returns SODR for true, CODR for false)
260+
* @param pin The pin to get the register for
261+
* @return The address for the register.
262+
*/
200263
WoReg *get_pio_reg(bool state, uint8_t pin);
201264

265+
/**
266+
* Gets the register for the chipselect pin
267+
* @param state The state for the pin
268+
* @return The address for the register
269+
*/
202270
WoReg *get_cs_pio_reg(bool state) {
203271
return get_pio_reg(state, _csPin);
204272
}
205273

274+
/**
275+
* Adds an entry to toggle a pin high or low
276+
* @param state The new state of the pin
277+
* @param pin The pin number
278+
* @param pin_mask_ptr A pointer to somewhere with the mask for that pin. The g_APinDescriptor will not work for this purpose.
279+
* @param num_transfers How many transfers to send.
280+
* @return Whether or not the entry was added to the buffer
281+
*/
206282
bool add_entry_pin_toggle(bool state, uint8_t pin, const uint32_t *pin_mask_ptr, size_t num_transfers = 2);
207283

284+
/**
285+
* Specifically adds an entry to toggle the CS pin
286+
* @param state The new state for the pin
287+
* @param num_transfers How many transfers to send. The RA chip requires that CS be high for ~5 CLK cycles before going low again.
288+
* @return Whether or not the entry was added to the buffer.
289+
*/
208290
bool add_entry_cs_pin_toggle(bool state, size_t num_transfers = 2);
209291

292+
/**
293+
* Adds a generic SPI transfer to the list
294+
* @param buf The start of the data to transfer.
295+
* @param qty The number of bytes in the buffer.
296+
* @return Whether or not the entry was added to the list
297+
*/
210298
bool add_entry_spi_transfer(volatile uint8_t *buf, size_t qty);
211299

300+
/**
301+
* Adds all the necessary entries to draw a batch of pixels in an area.
302+
* @param buf The buffer of pixels to add
303+
* @param qty The number of pixels drawn
304+
* @return uint8_t ptr to the start of the working data containing the draw commands (RA8875_CMDWRITE, DATAWRITE, etc)
305+
*/
212306
volatile uint8_t *add_entry_spi_draw_pixels(volatile uint8_t *buf, size_t qty);
213307

214308
/**

DMAManagerDue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ size_t DMAManager::get_size() const {
101101
return size;
102102
}
103103

104-
bool DMAManager::can_add_entries(uint32_t entries) const {
104+
bool DMAManager::can_add_entries(size_t entries) const {
105105
bool result = size + entries <= LLI_MAX_FRAMES;
106106
return result;
107107
}

DMA_LLI.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
#ifndef ADAFRUIT_RA8875_DMA_LLI_H
22
#define ADAFRUIT_RA8875_DMA_LLI_H
33

4+
/*******************************************
5+
*
6+
* Add whatever includes necessary to implement your DMA controller logic.
7+
* Currently only supports Arduino Due
8+
*
9+
********************************************/
10+
411

512
#if defined(ARDUINO_SAM_DUE)
613

DMA_LLI_Due.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55

66
typedef uint32_t Word;
77

8+
/**
9+
* Bitfield for CTRLA register.
10+
*/
811
typedef volatile union _CTRLA_Field {
912
_CTRLA_Field() : raw(0) {};
1013

@@ -25,6 +28,9 @@ typedef volatile union _CTRLA_Field {
2528
Word raw;
2629
} CTRLA_Field;
2730

31+
/**
32+
* Bitfield for CTRLB Register
33+
*/
2834
typedef volatile union _CTRLB_Field {
2935
_CTRLB_Field() : _CTRLB_Field(0) {};
3036

SpiDriver.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,26 +36,69 @@ class SpiDriver {
3636
public:
3737
explicit SpiDriver(uint8_t csPin, bool interrupts = false);
3838

39+
/**
40+
* Activates the driver. Similar to SPI.beginTransaction or setting clock div, etc.
41+
*/
3942
void activate();
4043

44+
/**
45+
* Deactivates the driver after activate(). Similar to SPI.endTransaction
46+
*/
4147
void deactivate();
4248

49+
/**
50+
* Starts SPI. Usually wraps SPI.begin()
51+
*/
4352
void begin();
4453

54+
/**
55+
* Ends SPI. Usually wraps SPI.end()
56+
*/
4557
void end();
4658

59+
/**
60+
* Reads 1 byte from SPI
61+
* @return Read data
62+
*/
4763
uint8_t receive();
4864

65+
/**
66+
* Reads 2 bytes
67+
* @return Bytes read
68+
*/
4969
uint16_t receive16();
5070

71+
/**
72+
* Read n bytes
73+
* @param buf buffer to read into
74+
* @param count number of bytes to read
75+
* @return A status code
76+
*/
5177
uint8_t receive(uint8_t *buf, size_t count);
5278

79+
/**
80+
* Sends 1 byte
81+
* @param data Data to send
82+
*/
5383
void send(uint8_t data);
5484

85+
/**
86+
* Sends 2 bytes of data
87+
* @param data The data to send
88+
*/
5589
void send16(uint16_t data);
5690

91+
/**
92+
* Send n bytes
93+
* @param buf The start of the buffer to send
94+
* @param count Number of bytes
95+
*/
5796
void send(uint8_t *buf, size_t count);
5897

98+
/**
99+
* Sets the clock speed for the SPI controller
100+
* @param speed Speed in Hz
101+
*/
59102
inline void setClockSpeed(uint32_t speed) {
60103
#if SPI_HAS_TRANSACTION
61104
_spiSettings = SPISettings(speed, MSBFIRST, SPI_MODE0);
@@ -64,12 +107,23 @@ class SpiDriver {
64107

65108
#if USE_DMA_INTERRUPT
66109

110+
/**
111+
* Get the underlying DMA manager, if available.
112+
* @return The Manager
113+
*/
67114
DMAManager *getDMAManager() {
68115
return &dmaManager;
69116
}
70117

118+
/**
119+
* Sends a chain of DMA frames, if available
120+
* @param head The start of the chain.
121+
*/
71122
void sendChain(volatile LLI *head);
72123

124+
/**
125+
* Starts the next chain of DMA operations
126+
*/
73127
void nextDMA();
74128

75129
#endif

0 commit comments

Comments
 (0)