Paparazzi UAS  v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
sdlogger_spi_direct.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) Bart Slinger
3  *
4  * This file is part of paparazzi
5  *
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  */
30 #define PERIODIC_C_LOGGER
31 
36 #include "led.h"
37 
38 #include <stdbool.h>
39 
40 #if SDLOGGER_ON_ARM
41 #include "autopilot.h"
42 #endif
43 
44 #ifdef LOGGER_LED
45 #define LOGGER_LED_ON LED_ON(LOGGER_LED);
46 #define LOGGER_LED_OFF LED_OFF(LOGGER_LED);
47 #else
48 #define LOGGER_LED_ON {}
49 #define LOGGER_LED_OFF {}
50 #endif
51 
52 #ifndef TELEMETRY_MODE_Main_empty
53 #warning You need to define a main telemetry mode named "empty" without any \
54  messages in your config file in /conf/telemetry/<your_config.xml>. \
55  \
56  Add <mode name="empty"></mode> to your main telemetry process.
57 #endif
58 
59 #ifndef TELEMETRY_PROCESS_Logger
60 #error "You need to use a telemetry xml file with Logger process!"
61 #endif
62 
63 #ifndef SDLOGGER_DOWNLOAD_DEVICE
64 #error No downlink device defined for SD Logger
65 #endif
66 
67 #ifdef SDLOGGER_DOWNLOAD_DEVICE_LISTEN
68 // Listen for setting commands on download port
69 #include "pprzlink/dl_protocol.h"
70 #include "generated/settings.h"
71 
72 #include <string.h>
73 
74 PRINT_CONFIG_MSG("Listening to SETTING on SD logger download port.");
75 
76 static struct download_port_t {
77  struct link_device *device;
78  struct pprz_transport transport;
79  bool msg_available;
80  uint8_t msg_buf[256];
81 } download_port;
82 
83 static void sdlogger_spi_direct_download_port_init(void) {
84  download_port.device = &((SDLOGGER_DOWNLOAD_DEVICE).device);
85  pprz_transport_init(&download_port.transport);
86 }
87 
88 static void sdlogger_spi_direct_download_port_parse_msg(void) {
89  switch (IdOfPprzMsg(download_port.msg_buf)) {
90  case DL_SETTING: {
91  uint8_t index = DL_SETTING_index(download_port.msg_buf);
92  uint8_t ac_id = DL_SETTING_ac_id(download_port.msg_buf);
93  float value = DL_SETTING_value(download_port.msg_buf);
94  if (ac_id == AC_ID) {
95  DlSetting(index, value);
96  pprz_msg_send_DL_VALUE(&download_port.transport.trans_tx, download_port.device, AC_ID, &index, &value);
98  }
99  break; }
100  default:
101  break;
102  }
103 }
104 
105 static void sdlogger_spi_direct_download_port_periodic(void) {
106  pprz_check_and_parse(download_port.device, &download_port.transport, download_port.msg_buf, &download_port.msg_available);
107  if (download_port.msg_available) {
108  sdlogger_spi_direct_download_port_parse_msg();
109  download_port.msg_available = false;
110  }
111 }
112 #endif // SDLOGGER_DOWNLOAD_DEVICE_LISTEN
113 
115 
121 {
122  /* Initialize the SD Card */
123  sdcard_spi_init(&sdcard1, &(SDLOGGER_SPI_LINK_DEVICE),
124  SDLOGGER_SPI_LINK_SLAVE_NUMBER);
125 
126  /* Set values in the struct to their defaults */
131 
132  /* Fill internal buffer with zeros */
133  for (uint8_t i = 0; i < sizeof(sdlogger_spi.buffer); i++) {
134  sdlogger_spi.buffer[i] = 0;
135  }
136  sdlogger_spi.idx = 0;
137  sdlogger_spi.log_len = 0;
138  sdlogger_spi.command = 0;
142  sdlogger_spi.do_log = 0;
143 
144  /* Set function pointers in link_device to the logger functions */
145  sdlogger_spi.device.check_free_space = (check_free_space_t)sdlogger_spi_direct_check_free_space;
146  sdlogger_spi.device.put_byte = (put_byte_t)sdlogger_spi_direct_put_byte;
147  sdlogger_spi.device.put_buffer = (put_buffer_t)sdlogger_spi_direct_put_buffer;
148  sdlogger_spi.device.send_message = (send_message_t)sdlogger_spi_direct_send_message;
149  sdlogger_spi.device.char_available = (char_available_t)sdlogger_spi_direct_char_available;
150  sdlogger_spi.device.get_byte = (get_byte_t)sdlogger_spi_direct_get_byte;
151  sdlogger_spi.device.periph = &sdlogger_spi;
152 
153 #ifdef SDLOGGER_DOWNLOAD_DEVICE_LISTEN
154  sdlogger_spi_direct_download_port_init();
155 #endif
156 }
157 
163 {
164 #ifdef SDLOGGER_DOWNLOAD_DEVICE_LISTEN
165  sdlogger_spi_direct_download_port_periodic();
166 #endif
167 
169 
170 #if SDLOGGER_ON_ARM
172  sdlogger_spi.do_log = 1;
173  } else {
174  sdlogger_spi.do_log = 0;
175  }
176 #endif
177 
178  switch (sdlogger_spi.status) {
180  if (sdcard1.status == SDCard_Idle) {
183  }
184  break;
185 
186  case SDLogger_Ready:
187  if ((sdlogger_spi.do_log == 1) &&
192  }
193  break;
194 
195  case SDLogger_Logging:
196  /* This line is NOT unit-tested because it is an inline function */
197  #if PERIODIC_TELEMETRY
198  periodic_telemetry_send_Logger(DefaultPeriodic,
199  &pprzlog_tp.trans_tx,
201  #endif
202  /* Check if SD Card buffer is full and SD Card is ready for new data */
203  if (sdlogger_spi.sdcard_buf_idx > 512 &&
206  }
207  /* Check if switch is flipped to stop logging */
208  if (sdlogger_spi.do_log == 0) {
210  }
211  break;
212 
215  if (sdlogger_spi.sdcard_buf_idx > 512) {
217  }
218  else if (sdlogger_spi.sdcard_buf_idx > 1) {
219  /* Fill with trailing zero's */
220  for (uint16_t i = sdlogger_spi.sdcard_buf_idx; i < (SD_BLOCK_SIZE+1); i++) {
221  sdcard1.output_buf[i] = 0x00;
222  }
224  }
225  else if (sdlogger_spi.sdcard_buf_idx == 1) {
228  }
229  }
230  break;
231 
233  if (sdcard1.status == SDCard_Idle) {
236  }
237  break;
238 
240  if (sdcard1.status == SDCard_Idle) {
243  }
244  break;
245 
247  if (sdcard1.status == SDCard_Idle) {
248  /* Put bytes to the buffer until all is written or buffer is full */
249  long fd = 0;
250  uint16_t chunk_size = 64;
251  for (uint16_t i = sdlogger_spi.sdcard_buf_idx; i < SD_BLOCK_SIZE && chunk_size > 0; i++, chunk_size--) {
252  if ((SDLOGGER_DOWNLOAD_DEVICE).device.check_free_space(&(SDLOGGER_DOWNLOAD_DEVICE), &fd, 1)) {
253  (SDLOGGER_DOWNLOAD_DEVICE).device.put_byte(&(SDLOGGER_DOWNLOAD_DEVICE), fd, sdcard1.input_buf[i]);
254  } else {
255  /* No free space left, abort for-loop */
256  break;
257  }
259  }
260  /* Request next block if entire buffer was written to uart */
262  (SDLOGGER_DOWNLOAD_DEVICE).device.send_message(&(SDLOGGER_DOWNLOAD_DEVICE), fd); // Flush buffers
263  if (sdlogger_spi.download_length > 0) {
267  }
268  else {
271  }
273  }
274  }
275  break;
276 
277  default:
278  break;
279  }
280 }
281 
284 
290 {
291 
292  switch (sdlogger_spi.status) {
296  // Save data for later use
298  (sdcard1.input_buf[1] << 16) |
299  (sdcard1.input_buf[2] << 8) |
300  (sdcard1.input_buf[3]);
302 
303  if(sdlogger_spi.next_available_address < 0x00004000) {
305  }
306 
307  /* Ready to start logging */
309  break;
310 
312  /* Copy input buffer to output buffer */
313  for (uint16_t i = 0; i < SD_BLOCK_SIZE; i++) {
315  }
316 
317  /* Increment last completed log */
319  /* Write log info at dedicated location */
320  {
321  uint16_t log_idx_start = 5 + 6 + (sdlogger_spi.last_completed - 1) * 12;
322 
323  /* Set start address and length at location that belongs to the log nr */
324  sdcard1.output_buf[log_idx_start+0] = sdlogger_spi.next_available_address >> 24;
325  sdcard1.output_buf[log_idx_start+1] = sdlogger_spi.next_available_address >> 16;
326  sdcard1.output_buf[log_idx_start+2] = sdlogger_spi.next_available_address >> 8;
327  sdcard1.output_buf[log_idx_start+3] = sdlogger_spi.next_available_address >> 0;
328  sdcard1.output_buf[log_idx_start+4] = sdlogger_spi.log_len >> 24;
329  sdcard1.output_buf[log_idx_start+5] = sdlogger_spi.log_len >> 16;
330  sdcard1.output_buf[log_idx_start+6] = sdlogger_spi.log_len >> 8;
331  sdcard1.output_buf[log_idx_start+7] = sdlogger_spi.log_len >> 0;
332  }
333 
334  /* Increment and update the next available address */
340 
341  sdcard_spi_write_block(&sdcard1, 0x00002000);
342  /* Reset log length */
343  sdlogger_spi.log_len = 0;
345  break;
346 
348  {
349  uint16_t info_idx = 5 + (sdlogger_spi.download_id - 1) * 12;
350  sdlogger_spi.download_address = (sdcard1.input_buf[info_idx+0] << 24) |
351  (sdcard1.input_buf[info_idx+1] << 16) |
352  (sdcard1.input_buf[info_idx+2] << 8) |
353  (sdcard1.input_buf[info_idx+3] << 0);
354  sdlogger_spi.download_length = (sdcard1.input_buf[info_idx+4] << 24) |
355  (sdcard1.input_buf[info_idx+5] << 16) |
356  (sdcard1.input_buf[info_idx+6] << 8) |
357  (sdcard1.input_buf[info_idx+7] << 0);
358  if (sdlogger_spi.download_length > 0) {
359  /* Request the first block */
361  /* After each read block, incr address, decr length */
365  }
366  else {
369  }
371  }
372  break;
373 
374  default:
375  break;
376  }
377 
378 }
379 
386 {
387  /* Increment log length */
389 
390  /* Copy data from logger buffer to SD Card buffer */
391  for (uint8_t i = 0; i < sdlogger_spi.idx; i++) {
393  }
394  /* Set sdcard buffer index to new value */
396  /* And reset the logger buffer index */
397  sdlogger_spi.idx = 0;
398 }
399 
401 {
403  sdlogger_spi.command < 43) {
405  sdcard_spi_read_block(&sdcard1, 0x00002000,
409  }
410  else if (sdcard1.status == SDCard_Idle && sdlogger_spi.command == 255) {
411  telemetry_mode_Main = TELEMETRY_MODE_Main_empty;
413  sdcard_spi_read_block(&sdcard1, 0x00002000, NULL);
417  }
418  /* Always reset command value back to zero */
419  sdlogger_spi.command = 0;
420 }
421 
422 int sdlogger_spi_direct_check_free_space(struct sdlogger_spi_periph *p, long *fd __attribute__((unused)), uint16_t len)
423 {
424  if (p->status == SDLogger_Logging) {
425  /* Calculating free space in both buffers */
426  int available = (513 - p->sdcard_buf_idx) + (SDLOGGER_BUFFER_SIZE - p->idx);
427  if (available >= len) {
428  return available;
429  }
430  }
431  return 0;
432 }
433 
434 void sdlogger_spi_direct_put_byte(struct sdlogger_spi_periph *p, long fd __attribute__((unused)), uint8_t data)
435 {
436  /* SD Buffer full, write in logger buffer */
437  if (p->sdcard_buf_idx > 512) {
438  if (p->idx < SDLOGGER_BUFFER_SIZE) {
439  p->buffer[p->idx++] = data;
440  }
441  /* else: data lost */
442  }
443  /* Writing directly to SD Card buffer */
444  else {
445  sdcard1.output_buf[p->sdcard_buf_idx++] = data;
446 
447  /* Flush buffer */
448  if (p->sdcard_buf_idx > 512 && sdcard1.status == SDCard_MultiWriteIdle) {
450  }
451  }
452 }
453 
455 {
456  int i;
457  for (i = 0; i < len; i++) {
458  sdlogger_spi_direct_put_byte(p, fd, data[i]);
459  }
460 }
461 
462 void sdlogger_spi_direct_send_message(void *p, long fd __attribute__((unused)))
463 {
464  (void) p;
465 }
466 
468  (void) p;
469  return 0;
470 }
471 
473 {
474  (void) p;
475  return 0;
476 }
477 
bool autopilot_get_motors_on(void)
get motors status
Definition: autopilot.c:290
Core autopilot interface common to all firmwares.
static float p[2][2]
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
arch independent LED (Light Emitting Diodes) API
struct pprzlog_transport pprzlog_tp
PPRZLOG transport structure.
Definition: pprzlog_tp.c:29
Initialize pprzlog transport.
void sdcard_spi_multiwrite_next(struct SDCard *sdcard, SDCardCallback callback)
Write a(nother) data block (512 bytes) to the SDCard.
Definition: sdcard_spi.c:638
void sdcard_spi_write_block(struct SDCard *sdcard, uint32_t addr)
Write a single block (512 bytes) to the SDCard at a given address.
Definition: sdcard_spi.c:560
void sdcard_spi_multiwrite_start(struct SDCard *sdcard, uint32_t addr)
Start writing multiple blocks of 512 bytes to the SDCard.
Definition: sdcard_spi.c:616
void sdcard_spi_read_block(struct SDCard *sdcard, uint32_t addr, SDCardCallback callback)
Read a single block (512 bytes) from the SDCard at a given address.
Definition: sdcard_spi.c:587
void sdcard_spi_periodic(struct SDCard *sdcard)
Periodic function of the SDCard.
Definition: sdcard_spi.c:99
struct SDCard sdcard1
This is the definition of the SD card.
Definition: sdcard_spi.c:56
void sdcard_spi_init(struct SDCard *sdcard, struct spi_periph *spi_p, const uint8_t slave_idx)
Configure initial values for SDCard.
Definition: sdcard_spi.c:74
void sdcard_spi_multiwrite_stop(struct SDCard *sdcard)
Stop with multiwrite procedure.
Definition: sdcard_spi.c:666
@ SDCard_MultiWriteIdle
CMD25 complete, ready to sent blocks.
Definition: sdcard_spi.h:84
@ SDCard_Idle
Initialization sequence succesful.
Definition: sdcard_spi.h:58
enum SDCardStatus status
The status of the SD card.
Definition: sdcard_spi.h:112
#define SD_BLOCK_SIZE
Definition: sdcard_spi.h:38
uint8_t output_buf[SD_BLOCK_SIZE+10]
The output buffer for the SPI transaction.
Definition: sdcard_spi.h:114
uint8_t input_buf[SD_BLOCK_SIZE+10]
The input buffer for the SPI transaction.
Definition: sdcard_spi.h:113
void sdlogger_spi_direct_index_received(void)
sdlogger_spi_direct_index_received Callback from SD Card when block at index location is received.
uint8_t sdlogger_spi_direct_get_byte(void *p)
void sdlogger_spi_direct_command(void)
void sdlogger_spi_direct_put_buffer(struct sdlogger_spi_periph *p, long fd, uint8_t *data, uint16_t len)
struct sdlogger_spi_periph sdlogger_spi
void sdlogger_spi_direct_init(void)
sdlogger_spi_direct_init Initialize the logger and SD Card.
void sdlogger_spi_direct_put_byte(struct sdlogger_spi_periph *p, long fd, uint8_t data)
void sdlogger_spi_direct_stop(void)
void sdlogger_spi_direct_multiwrite_written(void)
sdlogger_spi_direct_multiwrite_written Called when a multiwrite is complete.
void sdlogger_spi_direct_send_message(void *p, long fd)
#define LOGGER_LED_ON
void sdlogger_spi_direct_periodic(void)
sdlogger_spi_direct_periodic Periodic function called at module frequency
#define LOGGER_LED_OFF
int sdlogger_spi_direct_char_available(void *p)
int sdlogger_spi_direct_check_free_space(struct sdlogger_spi_periph *p, long *fd, uint16_t len)
void sdlogger_spi_direct_start(void)
uint8_t buffer[SDLOGGER_BUFFER_SIZE]
@ SDLogger_Initializing
@ SDLogger_StoppedLogging
@ SDLogger_RetreivingIndex
@ SDLogger_GettingIndexForDownload
@ SDLogger_UpdatingIndex
@ SDLogger_Ready
@ SDLogger_GettingIndexForUpdate
@ SDLogger_Logging
@ SDLogger_LoggingFinalBlock
@ SDLogger_Downloading
struct link_device device
enum SDLoggerStatus status
#define SDLOGGER_BUFFER_SIZE
int fd
Definition: serial.c:26
Periodic telemetry system header (includes downlink utility and generated code).
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
Definition: vl53l1_types.h:88
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.
Definition: vl53l1_types.h:98