SCAMP-5c SPI Interface  1.0.0
SCAMP-5c is connected to the flight computer via a SPI interface
scamp5c_spi.hpp
Go to the documentation of this file.
1 
18 #ifndef SCAMP5C_SPI_HPP
19 #define SCAMP5C_SPI_HPP
20 
21 #include <cstdio>
22 #include <cstdlib>
23 #include <cstdint>
24 #include <utility>
25 #include <algorithm>
26 #include <thread>
27 #include <atomic>
28 #include <mutex>
29 #include <list>
30 
31 #define RETURN_ERROR(v) return report_error(__func__,__LINE__,v)
32 #define REPORT_ERROR(v) report_error(__func__,__LINE__,v)
33 #define REPORT_WARNING(str) report_warning(__func__,__LINE__,str)
34 
35 #define SPI_PACKET_TYPE_NO_PAYLOAD 0
36 #define SPI_PACKET_TYPE_CONST_SIZE 1
37 #define SPI_PACKET_TYPE_OPEN_SIZE 2
38 #define SPI_PACKET_TYPE_COMMAND 3
39 
45 
46 public:
47 
48  #pragma pack(push)
49  #pragma pack(1)
50  struct packet_header{
51  uint8_t signature[3];
52  uint8_t packet_type;
53  uint32_t payload_size;
54  };
55  struct packet_header_cs{
56  uint8_t signature[3];
57  uint8_t check_byte[4];
58  uint8_t checksum;
59  };
60  #pragma pack(pop)
61 
62  const size_t SPI_TRANSFER_SIZE_MIN = 16;
63  const size_t SPI_TRANSFER_SIZE_MAX = 4096;
64  const size_t SPI_TRANSFER_SIZE_DEFAULT = 200;
65  const size_t PACKET_BUFFER_SIZE = 256*256*4;
66  const size_t PACKET_HEADER_LENGTH = sizeof(packet_header);
67  const uint8_t PACKET_SIGNATURE[3] = { 0x20, 0x16, 0xAA };
68 
73  class packet{
74 
75  friend class scamp5c_spi;
76 
77  protected:
78  uint32_t sn;
79  double time;
80  size_t size;
81  uint8_t* data;
82  packet_header *header_ptr;
83  uint8_t *payload_ptr;
84 
85  packet(){
86  sn = 0;
87  size = 0;
88  data = NULL;
89  header_ptr = NULL;
90  payload_ptr = NULL;
91  }
92 
93  public:
94 
101  inline uint32_t GetPayloadSize(){
102  return header_ptr->payload_size;
103  }
104 
111  inline uint8_t* GetPayload(){
112  return payload_ptr;
113  }
114 
115  inline uint8_t GetType(){
116  return header_ptr->packet_type;
117  }
118 
119  inline uint32_t GetSerialNumber(){
120  return sn;
121  }
122 
123  inline packet_header* GetHeader(){
124  return header_ptr;
125  }
126  };
127 
128  scamp5c_spi();
129  virtual ~scamp5c_spi();
130 
140  int OpenSPI(const char*dev_path,uint32_t d_clk = 2500000);
141 
146  int CloseSPI(void);
147 
154  int StartThreads();
155 
162  int EndThreads();
163 
170  inline void SetTransferSize(uint32_t s){
171  s = std::min(s,SPI_TRANSFER_SIZE_MAX);
172  s = std::max(s,SPI_TRANSFER_SIZE_MIN);
173  set_transfer_size(s);
174  }
175 
176  inline uint32_t GetTransferSize(){
177  return transfer_size_back;
178  }
179 
180  void ResetAllCounters();
181 
182  inline uint32_t GetTriggerCounter(){
183  return trigger_counter;
184  }
185  inline uint32_t GetTxSwapCounter(){
186  return tx_swap_counter;
187  }
188  inline uint32_t GetTransferCounter(){
189  return transfer_counter;
190  }
191  inline uint32_t GetSignatureCounter(){
192  return signature_counter;
193  }
194  inline uint32_t GetHeaderCounter(){
195  return header_counter;
196  }
197  inline uint32_t GetPacketCounter(){
198  return packet_counter;
199  }
200 
201 
206  inline size_t GetPacketQueueLength(){
207  size_t length;
208  section_packet_queue.lock();
209  length = packet_queue.size();
210  section_packet_queue.unlock();
211  return length;
212  }
213 
219  packet *p;
220  section_packet_queue.lock();
221  if(packet_queue.size() > 0){
222  p = packet_queue.front();
223  packet_queue.pop_front();
224  }else{
225  p = NULL;
226  }
227  section_packet_queue.unlock();
228  return p;
229  }
230 
235  inline void DeletePacket(packet*p){
236  if(p!=NULL){
237  free(p->data);
238  delete p;
239  }
240  }
241 
246  inline void OpenTxBuffer(){
247  section_tx_buffer.lock();
248  }
249 
254  inline uint8_t*GetTxBuffer(){
255  return tx_buf_back;
256  }
257 
262  inline void CloseTxBuffer(){
263  section_tx_buffer.unlock();
264  }
265 
266 protected:
267 
268  static int write_hex(const char*filepath,const uint8_t*data,size_t s);
269  static int report_error(const char*f_name,int line_num,int err_code);
270  static void report_warning(const char*f_name,int line_num,const char*text);
271 
272  int dev_file;
273 
274  uint8_t mode;
275  uint8_t bits;
276  uint32_t clock;
277 
278  std::thread *th_transfer;
279  std::thread *th_packet;
280  std::mutex section_transfer;
281  std::mutex section_tx_buffer;
282  std::mutex section_packet_queue;
283 
284  std::atomic<bool> control_quit;
285 
286 
287  volatile uint32_t trigger_counter;
288  volatile uint32_t transfer_counter;
289  volatile uint32_t tx_swap_counter;
290  volatile uint32_t signature_counter;
291  volatile uint32_t header_counter;
292  volatile uint32_t packet_counter;
293 
294  std::list<packet*> packet_queue;
295 
296  void spi_transfer_thread();
297  void spi_packet_thread();
298 
299  virtual void spi_cs_high();
300  virtual void spi_cs_low();
301  virtual bool spi_transfer_trigger();
302  virtual void save_rx_buf();
303  virtual void rtc_sleep_usec(uint32_t u_sec);
304 
305  // resize current packet buffer and put it in queue, then allocate a new packet buffer
306  void queue_packet_buffer();
307 
308  // function called once a transfer is finished, must return rx_buf offset
309  virtual size_t transfer_callback();
310 
311  // verify the header and wipe the checksum byte
312  virtual bool check_header(uint8_t*p);
313 
314  // function called once a header is acquired
315  virtual void header_callback(size_t rx_offset,packet_header*p);
316 
317  // function called once a command is acquired
318  virtual void command_callback(uint8_t command,uint8_t a,uint8_t b);
319 
320  // function called once a packet is acquired
321  virtual void packet_callback(size_t rx_offset);
322 
323 
324  inline uint8_t*get_rx_buffer(){
325  return rx_buf_back;
326  }
327  inline uint8_t*get_tx_buffer(){
328  return tx_buf_back;
329  }
330  inline uint32_t get_transfer_size(){
331  return transfer_size_back;
332  }
333  inline void set_transfer_size(uint32_t s){
334  transfer_size_next = s;
335  }
336 
337  inline uint8_t*get_packet_buffer(){
338  return packet_buffer;
339  }
340  inline size_t get_packet_length(){
341  return packet_length;
342  }
343 
344 private:
345 
346  uint8_t* tx_buf_a;
347  uint8_t* tx_buf_b;
348  uint8_t* volatile tx_buf_front;
349  uint8_t* volatile tx_buf_back;
350  uint8_t* rx_buf_a;
351  uint8_t* rx_buf_b;
352  uint8_t* volatile rx_buf_front;
353  uint8_t* volatile rx_buf_back;
354  volatile uint32_t transfer_size_next;
355  volatile uint32_t transfer_size_back;
356 
357  std::atomic<uint32_t> transfer_request;
358 
359  uint8_t* volatile packet_buffer;
360  size_t packet_length;
361 
362 
363 };
364 
365 #endif // SCAMP5C_SPI_HPP
void DeletePacket(packet *p)
delete a packet taken from the packet queue
Definition: scamp5c_spi.hpp:235
the SPI packet class
Definition: scamp5c_spi.hpp:73
uint8_t * GetPayload()
get the pointer to the payload data
Definition: scamp5c_spi.hpp:111
void OpenTxBuffer()
gain access to the transmit buffer
Definition: scamp5c_spi.hpp:246
uint8_t * GetTxBuffer()
get the pointer to the transmit buffer thus modify the content in it
Definition: scamp5c_spi.hpp:254
int CloseSPI(void)
close the spi interface
uint32_t GetPayloadSize()
get the size of the payload
Definition: scamp5c_spi.hpp:101
int StartThreads()
start running the internal functions in different threads
int EndThreads()
stop the interface and close all threads created in the background
void CloseTxBuffer()
release access to the transmit buffer
Definition: scamp5c_spi.hpp:262
void SetTransferSize(uint32_t s)
change the transfer size
Definition: scamp5c_spi.hpp:170
packet * PopPacketFromQueue()
get a packet from the queue as the packet is removed from queue
Definition: scamp5c_spi.hpp:218
size_t GetPacketQueueLength()
get the number of packet in the packet queue
Definition: scamp5c_spi.hpp:206
int OpenSPI(const char *dev_path, uint32_t d_clk=2500000)
open the spi interface
the object-oriented interface of the spi bus
Definition: scamp5c_spi.hpp:44