Paparazzi UAS  v5.15_devel-230-gc96ce27
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
max7456.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Chris
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, write to
18  * the Free Software Foundation, 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
21 
28 #include "std.h"
29 //#include "stdio.h"
30 
31 #include "mcu_periph/sys_time.h"
32 #include "mcu_periph/gpio.h"
33 #include "mcu_periph/spi.h"
34 
35 #include "generated/flight_plan.h"
36 #include "generated/airframe.h"
37 #include "autopilot.h"
38 #include "subsystems/electrical.h"
39 #include "state.h"
40 
41 // for GetPosAlt, include correct header until we have unified API
42 #ifdef AP
43 #include "subsystems/navigation/nav.h"
44 #else
46 #endif
47 
48 // Peripherials
51 
52 #define OSD_STRING_SIZE 31
53 #define osd_sprintf _osd_sprintf
54 
55 static char ascii_to_osd_c(char c);
56 static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column);
57 static bool _osd_sprintf(char *buffer, char *string, float value);
58 
60 
65 char osd_char = ' ';
68 uint8_t osd_attr = false;
69 
82 };
83 
87 };
88 
93 bool osd_stat_reg_valid = false;
94 
95 void max7456_init(void)
96 {
97 
98  max7456_trans.slave_idx = MAX7456_SLAVE_IDX;
109  max7456_trans.before_cb = NULL;
110  max7456_trans.after_cb = NULL;
111 
112  osd_enable = 1;
115 
116  return;
117 }
118 
120 {
121 
122  float temp = 0;
123 //This code is executed always and checks if the "osd_enable" var has been changed by telemetry.
124 //If yes then it commands a reset but this time turns on or off the osd overlay, not the video.
125  if (max7456_osd_status == OSD_IDLE) {
126  if (osd_enable > 1) {
127  osd_enable = 1;
128  }
129  if ((osd_enable << 3) != osd_enable_val) {
130  osd_enable_val = (osd_enable << 3);
132  }
133  }
134 
135  //INITIALIZATION OF THE OSD
137  step = 0;
140  //This operation needs at least 100us but when the periodic function will be invoked again
141  //sufficient time will have elapsed even with at a periodic frequency of 1000 Hz
144  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
145  } else if (max7456_osd_status == OSD_INIT2) {
150  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
151  } else if (max7456_osd_status == OSD_IDLE && osd_enable > 0) { // DRAW THE OSD SCREEN
152  //draw_osd();
153  switch (step) {
154  case (0):
155  osd_put_s("HDG", FALSE, 3, 0, 13);
156  step = 10;
157  break;
158  case (10):
161  osd_put_s(osd_string, FALSE, 8, 0, 2);
162  } else {
163  osd_put_s(osd_string, BLINK | INVERT, 8, 0, 2);
164  }
165  step = 20;
166  break;
167  case (20):
168 #if MAG_HEADING_AVAILABLE && !defined(SITL)
169  temp = DegOfRad(MAG_Heading);
170  if (temp < 0) {
171  temp += 360;
172  }
173 #else
174  temp = DegOfRad(state.h_speed_dir_f);
175  if (temp < 0) {
176  temp += 360;
177  }
178 #endif
179  osd_sprintf(osd_string, "%.0f", temp);
180  osd_put_s(osd_string, FALSE, 8, 1, 13);
181  step = 30;
182  break;
183  case (30):
184  osd_sprintf(osd_string, "%.0fKm", (state.h_speed_norm_f * 3.6));
185  osd_put_s(osd_string, FALSE, 8, 0, 24);
186  step = 40;
187  break;
188  case (40):
189  osd_sprintf(osd_string, "%.0fm", GetPosAlt());
190  osd_put_s(osd_string, FALSE, 10, 13, 2);
191  step = 50;
192  break;
193  case (50):
194  osd_sprintf(osd_string, "%.1fVZ", stateGetSpeedEnu_f()->z);
195  osd_put_s(osd_string, FALSE, 7, 13, 24);
196  step = 10;
197  break;
198  default: break;
199  }
200  }
201  return;
202 }
203 
204 void max7456_event(void)
205 {
206 
207  static uint8_t x = 0;
208 
211 
212  switch (max7456_osd_status) {
213  case (OSD_INIT1):
215  break;
216  case (OSD_INIT3):
220  max7456_trans.output_buf[1] = max7456_trans.input_buf[0] & (~(1 << 4));
222  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
223  break;
224  case (OSD_INIT4):
226 #if USE_PAL_FOR_OSD_VIDEO
228 #else
230 #endif
232  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
233  break;
234  case (OSD_READ_STATUS):
236  osd_stat_reg_valid = true;
238  break;
239  case (OSD_S_STEP1):
244  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
245  break;
246  case (OSD_S_STEP2):
251  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
252  x = 0;
253  break;
254  case (OSD_S_STEP3):
255  max7456_trans.output_length = 1; //1 byte tranfers, auto address incrementing.
256  if (osd_string[x] != 0XFF) {
258  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
259  } else {
260  max7456_trans.output_buf[0] = 0xFF; //Exit the auto increment mode
262  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
263  }
264  break;
265  case (OSD_FINISHED):
266  osd_attr = 0;
269  break;
270  default: break;
271  }
272  }
273  return;
274 }
275 
276 static char ascii_to_osd_c(char c)
277 {
278 
279  if (c >= '0' && c <= '9') {
280  if (c == '0') {
281  c -= 38;
282  } else {
283  c -= 48;
284  }
285  } else {
286  if (c >= 'A' && c <= 'Z') {
287  c -= 54;
288  } else {
289  if (c >= 'a' && c <= 'z') {
290  c -= 60;
291  } else {
292  switch (c) {
293  case ('('): c = 0x3f; break;
294  case (')'): c = 0x40; break;
295  case ('.'): c = 0x41; break;
296  case ('?'): c = 0x42; break;
297  case (';'): c = 0x43; break;
298  case (':'): c = 0x44; break;
299  case (','): c = 0x45; break;
300  //case('''): c = 0x46; break;
301  case ('/'): c = 0x47; break;
302  case ('"'): c = 0x48; break;
303  case ('-'): c = 0x49; break;
304  case ('<'): c = 0x4A; break;
305  case ('>'): c = 0x4B; break;
306  case ('@'): c = 0x4C; break;
307  case (' '): c = 0x00; break;
308  case ('\0'): c = 0xFF; break;
309  default : break;
310  }
311  }
312  }
313  }
314  return (c);
315 }
316 
317 static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column)
318 {
319 
320  uint8_t x = 0;
321 
322  if (row > 15) {
323  column = 15;
324  }
325  if (column > 29) {
326  column = 29;
327  }
328  osd_char_address = ((uint16_t)row * 30) + column;
329 
330  // translate the string and put it to the "osd_string" '\0' = 0xff
331  x = 0;
332  while ( (*(string + x) != '\0') && ( x < (sizeof(osd_string)-1) )) {
333  osd_string[x] = ascii_to_osd_c(*(string + x));
334  x++;
335  }
336  osd_string[x] = ascii_to_osd_c(*(string + x));
337 
338  for (x = 0; x < sizeof(osd_string); x++) {
339  if (osd_string[x] == 0xff) {
340  break;
341  }
342  }
343 
344  // Prevent overflow condition
345  if (char_nb >= OSD_STRING_SIZE) {
346  char_nb = OSD_STRING_SIZE-1;
347  }
348  //Adjust for the reserved character number.
349  for (; x < char_nb; x++) {
350  osd_string[x] = 0;
351  }
352  osd_string[x] = 0xff;
353 
354  osd_attr = attributes;
355 
356  //TRIGGER THE SPI TRANSFERS. The rest of the spi transfers occur in the "max7456_event" function.
357  if (max7456_osd_status == OSD_IDLE) {
360  max7456_trans.output_buf[1] = (uint8_t)((osd_char_address >> 8) & 0x0001);
362  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
363  }
364  return;
365 }
366 
367 // A VERY VERY STRIPED DOWN sprintf function suitable only for the paparazzi OSD.
368 static bool _osd_sprintf(char *buffer, char *string, float value)
369 {
370 
371  uint8_t param_start = 0;
372  uint8_t param_end = 0;
373  uint8_t frac_nb = 0;
374  uint8_t digit = 0;
375  uint8_t x = 0, y = 0, z = 0;
376 
377  uint16_t i_dec = 0;
378  uint16_t i_frac = 0;
379 
380  char to_asc[10] = {48, 48, 48, 48, 48, 48, 48, 48, 48, 48};
381 
382  // Clear the osd string.
383  for (x = 0; x < sizeof(osd_string); x++) {
384  osd_string[x] = 0;
385  }
386  x = 0;
387  // Search for the prameter start and stop positions.
388  while (*(string + x) != '\0') {
389  if (*(string + x) == '%') {
390  param_start = x;
391  } else if (*(string + x) == 'f') {
392  param_end = x;
393  break;
394  }
395  x++;
396  }
397  // find and bound the precision specified.
398  frac_nb = *(string + param_end - 1) - 48; // Convert to number, ASCII 48 = '0'
399  if (frac_nb > 3) {
400  frac_nb = 3; // Bound value.
401  }
402  // Point y to one before the end of the array
403  // Because we will increment it with frac_nb-1, so pointing it to the end would result in overflow
404  y = (sizeof(to_asc) - 3);
405  i_dec = abs((int16_t)value);
406  // Fist we will deal with the fractional part if specified.
407  if (frac_nb > 0 && frac_nb <= 3) {
408  i_frac = abs((int16_t)((value - (int16_t)value) * 1000)); // Max precision is 3 digits.
409  x = 100;
410  z = frac_nb;
411  do { // Example if frac_nb=2 then 952 will show as .95
412  z--;
413  digit = (i_frac / x);
414  to_asc[y + z] = digit + 48; // Convert to ASCII
415  i_frac -= digit * x; // Calculate the remainder.
416  x /= 10; // 952-(9*100) = 52, 52-(10*5)=2 etc.
417  } while (z > 0);
418  y -= frac_nb; // set y to point where the dot must be placed.
419  to_asc[y] = '.';
420  y--; // Set y to point where the rest of the numbers must be written.
421  }
422 
423  // Now it is time for the integer part. "y" already points to the position just before the dot.
424  do {
425  to_asc[y] = (i_dec % 10) + 48; //Write at least one digit even if value is zero.
426  i_dec /= 10;
427  if (i_dec <= 0) { // This way the leading zero is ommited.
428  if (value < 0) {
429  y--; to_asc[y] = '-'; // Place the minus sign if needed.
430  }
431  break;
432  } else {
433  y--;
434  }
435  } while (1);
436 
437  // Fill the buffer with the characters in the beggining of the string if any.
438  for (x = 0; x < param_start; x++) {
439  *(buffer + x) = *(string + x);
440  }
441 
442  // x is now pointing to the next character in osd_string.
443  // y is already pointing to the first digit or negative sign in "to_asc" array.
444  while (y < sizeof(to_asc)) {
445  *(buffer + x) = to_asc[y];
446  x++; y++;
447  }
448  // x is now pointing to the next character in osd_string.
449  // "param_end" is pointing to the last format character in the string.
450  do {
451  param_end++;
452  *(buffer + x++) = *(string + param_end);
453  } while (*(string + param_end) != '\0'); //Write the rest of the string including the terminating char.
454 
455  return (0);
456 }
max7456_osd_status_codes
Definition: max7456.c:70
unsigned short uint16_t
Definition: types.h:16
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:155
char osd_char
Definition: max7456.c:65
char osd_str_buf[OSD_STRING_SIZE]
Definition: max7456.c:64
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:159
uint16_t output_length
number of data words to write
Definition: spi.h:152
#define OSD_BLINK_CHAR
Definition: max7456_regs.h:53
Maxim MAX7456 single-channel monochrome on-screen display driver.
float h_speed_dir_f
Direction of horizontal ground speed.
Definition: state.h:321
#define LOW_BAT_LEVEL
low battery level in Volts (for 3S LiPo)
Definition: electrical.h:36
Some architecture independent helper functions for GPIOs.
void max7456_init(void)
Definition: max7456.c:95
bool osd_stat_reg_valid
Definition: max7456.c:93
float h_speed_norm_f
Norm of horizontal ground speed.
Definition: state.h:315
Maxim MAX7456 single-channel monochrome on-screen display driver.
SPI transaction structure.
Definition: spi.h:148
osd_attributes
Definition: max7456.c:84
float vsupply
supply voltage in V
Definition: electrical.h:45
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:511
#define OSD_DMM_REG
Definition: max7456_regs.h:36
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:158
#define OSD_DMAH_REG
Definition: max7456_regs.h:37
#define OSD_IMAGE_ENABLE
Definition: max7456_regs.h:48
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:150
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:154
#define OSD_RESET
Definition: max7456_regs.h:50
#define FALSE
Definition: std.h:5
#define osd_sprintf
Definition: max7456.c:53
Architecture independent SPI (Serial Peripheral Interface) API.
#define OSD_AUTO_INCREMENT_MODE
Definition: max7456_regs.h:56
void max7456_event(void)
Definition: max7456.c:204
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:156
uint8_t osd_stat_reg
Definition: max7456.c:92
#define OSD_OSDBL_REG_R
Definition: max7456_regs.h:41
#define OSD_OSDBL_REG
Definition: max7456_regs.h:40
struct spi_transaction max7456_trans
Definition: max7456.c:59
Definition: spi.h:90
static bool _osd_sprintf(char *buffer, char *string, float value)
Definition: max7456.c:368
Interface for electrical status: supply voltage, current, battery status, etc.
Architecture independent timing functions.
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:161
char osd_string[OSD_STRING_SIZE]
Definition: max7456.c:63
signed short int16_t
Definition: types.h:17
uint8_t osd_attr
Definition: max7456.c:68
CPOL = 0.
Definition: spi.h:83
uint8_t step
Definition: max7456.c:66
Definition: max7456.c:86
uint16_t input_length
number of data words to read
Definition: spi.h:151
#define OSD_DMAL_REG
Definition: max7456_regs.h:38
#define OSD_VM0_REG
Definition: max7456_regs.h:34
uint8_t max7456_osd_status
Definition: max7456.c:89
Core autopilot interface common to all firmwares.
Rotorcraft navigation functions.
#define OSD_INVERT_PIXELS
Definition: max7456_regs.h:54
static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column)
Definition: max7456.c:317
#define OSD_VIDEO_MODE_PAL
Definition: max7456_regs.h:45
unsigned char uint8_t
Definition: types.h:14
API to get/set the generic vehicle states.
void max7456_periodic(void)
Definition: max7456.c:119
static struct EnuCoor_f * stateGetSpeedEnu_f(void)
Get ground speed in local ENU coordinates (float).
Definition: state.h:917
CPHA = 0.
Definition: spi.h:74
#define OSD_STRING_SIZE
Definition: max7456.c:52
uint8_t osd_enable_val
Definition: max7456.c:91
slave is selected before transaction and unselected after
Definition: spi.h:63
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:157
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:153
uint8_t osd_spi_tx_buffer[2]
Definition: max7456.c:61
Definition: spi.h:125
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:149
SPICallback before_cb
NULL or function called before the transaction.
Definition: spi.h:160
uint8_t osd_enable
Definition: max7456.c:90
struct Electrical electrical
Definition: electrical.c:66
uint16_t osd_char_address
Definition: max7456.c:67
Definition: max7456.c:85
uint8_t osd_spi_rx_buffer[2]
Definition: max7456.c:62
struct State state
Definition: state.c:36
enum SPITransactionStatus status
Definition: spi.h:162
static char ascii_to_osd_c(char c)
Definition: max7456.c:276