Paparazzi UAS  v5.2.2_stable-0-gd6b9f29
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures 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 #include "led.h"
35 #include "autopilot.h"
36 
38 #include "generated/flight_plan.h"
39 #include "generated/airframe.h"
41 #include "subsystems/electrical.h"
42 
43 #include "messages.h"
45 #include "state.h"
46 
47 // Peripherials
48 #include "max7456.h"
49 #include "max7456_regs.h"
50 
51 #define OSD_STRING_SIZE 31
52 #define osd_sprintf _osd_sprintf
53 
54 static char ascii_to_osd_c( char c);
55 static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column);
56 static bool_t _osd_sprintf(char* buffer, char* string, float value);
57 
59 
64 char osd_char = ' ';
68 
81 };
82 
86 };
87 
93 
94 void max7456_init(void) {
95 
96  max7456_trans.slave_idx = MAX7456_SLAVE_IDX;
107  max7456_trans.before_cb = NULL;
108  max7456_trans.after_cb = NULL;
109 
110  osd_enable = 1;
113 
114  return;
115 }
116 
117 void max7456_periodic(void) {
118 
119  float temp = 0;
120 //This code is executed always and checks if the "osd_enable" var has been changed by telemetry.
121 //If yes then it commands a reset but this time turns on or off the osd overlay, not the video.
122  if (max7456_osd_status == OSD_IDLE) {
123  if(osd_enable > 1)
124  osd_enable = 1;
125  if ((osd_enable<<3) != osd_enable_val) {
126  osd_enable_val = (osd_enable<<3);
128  }
129  }
130 
131  //INITIALIZATION OF THE OSD
133  step = 0;
136  //This operation needs at least 100us but when the periodic function will be invoked again
137  //sufficient time will have elapsed even with at a periodic frequency of 1000 Hz
140  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
141  }
142  else
143  if (max7456_osd_status == OSD_INIT2) {
148  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
149  }
150  else
151  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):
159  temp = ((float)electrical.vsupply)/10;
160  osd_sprintf(osd_string, "%.1fV", temp );
161  if (temp > LOW_BAT_LEVEL)
162  osd_put_s(osd_string, FALSE, 8, 0, 2);
163  else
164  osd_put_s(osd_string, BLINK|INVERT, 8, 0, 2);
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  #else
173  temp = DegOfRad(state.h_speed_dir_f);
174  if (temp < 0)
175  temp += 360;
176  #endif
177  osd_sprintf(osd_string, "%.0f", temp);
178  osd_put_s(osd_string, FALSE, 8, 1, 13);
179  step = 30;
180  break;
181  case (30):
182  osd_sprintf(osd_string, "%.0fKm", (state.h_speed_norm_f*3.6));
183  osd_put_s(osd_string, FALSE, 8, 0, 24);
184  step = 40;
185  break;
186  case (40):
187  osd_sprintf(osd_string, "%.0fm", GetPosAlt() );
188  osd_put_s(osd_string, FALSE, 10, 13, 2);
189  step = 50;
190  break;
191  case (50):
192  osd_sprintf(osd_string, "%.1fVZ", stateGetSpeedEnu_f()->z);
193  osd_put_s(osd_string, FALSE, 7, 13, 24);
194  step = 10;
195  break;
196  default: break;
197  }
198  }
199  return;
200 }
201 
202 void max7456_event(void) {
203 
204  static uint8_t x = 0;
205 
208 
209  switch (max7456_osd_status) {
210  case (OSD_INIT1):
212  break;
213  case (OSD_INIT3):
217  max7456_trans.output_buf[1] = max7456_trans.input_buf[0] & (~(1<<4));
219  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
220  break;
221  case (OSD_INIT4):
223 #if USE_PAL_FOR_OSD_VIDEO
225 #else
227 #endif
229  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
230  break;
231  case (OSD_READ_STATUS):
235  break;
236  case (OSD_S_STEP1):
241  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
242  break;
243  case (OSD_S_STEP2):
248  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
249  x = 0;
250  break;
251  case (OSD_S_STEP3):
252  max7456_trans.output_length = 1; //1 byte tranfers, auto address incrementing.
253  if (osd_string[x] != 0XFF) {
255  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
256  }
257  else {
258  max7456_trans.output_buf[0] = 0xFF; //Exit the auto increment mode
260  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
261  }
262  break;
263  case (OSD_FINISHED):
264  osd_attr = 0;
267  break;
268  default: break;
269  }
270  }
271  return;
272 }
273 
274 static char ascii_to_osd_c(char c) {
275 
276  if (c >= '0' && c <= '9') {
277  if (c == '0')
278  c -= 38;
279  else
280  c -= 48;
281  }
282  else {
283  if (c >= 'A' && c <= 'Z')
284  c -= 54;
285  else {
286  if (c >= 'a' && c <= 'z')
287  c -= 60;
288  else {
289  switch (c) {
290  case('('): c = 0x3f; break;
291  case(')'): c = 0x40; break;
292  case('.'): c = 0x41; break;
293  case('?'): c = 0x42; break;
294  case(';'): c = 0x43; break;
295  case(':'): c = 0x44; break;
296  case(','): c = 0x45; break;
297  //case('''): c = 0x46; break;
298  case('/'): c = 0x47; break;
299  case('"'): c = 0x48; break;
300  case('-'): c = 0x49; break;
301  case('<'): c = 0x4A; break;
302  case('>'): c = 0x4B; break;
303  case('@'): c = 0x4C; break;
304  case(' '): c = 0x00; break;
305  case('\0'): c = 0xFF; break;
306  default : break;
307  }
308  }
309  }
310  }
311  return(c);
312 }
313 
314 static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column){
315 
316  uint8_t x=0;
317 
318  if (row > 15)
319  column = 15;
320  if (column > 29)
321  column = 29;
322  osd_char_address = ((uint16_t)row*30) + column;
323 
324  // translate the string and put it to the "osd_string" '\0' = 0xff
325  x = 0;
326  while (*(string+x) != '\0') {
327  osd_string[x] = ascii_to_osd_c(*(string+x));
328  x++;
329  }
330  osd_string[x] = ascii_to_osd_c(*(string+x));
331 
332  for (x=0; x < sizeof(osd_string); x++) {
333  if(osd_string[x] == 0xff)
334  break;
335  }
336 
337  //Adjust for the reserved character number.
338  for (; x< char_nb; x++) {
339  osd_string[x] = 0;
340  }
341  osd_string[x] = 0xff;
342 
343  osd_attr = attributes;
344 
345  //TRIGGER THE SPI TRANSFERS. The rest of the spi transfers occur in the "max7456_event" function.
349  max7456_trans.output_buf[1] = (uint8_t)((osd_char_address>>8) & 0x0001);
351  spi_submit(&(MAX7456_SPI_DEV), &max7456_trans);
352  }
353  return;
354 }
355 
356 // A VERY VERY STRIPED DOWN sprintf function suitable only for the paparazzi OSD.
357 static bool_t _osd_sprintf(char* buffer, char* string, float value) {
358 
359  uint8_t param_start = 0;
360  uint8_t param_end = 0;
361  uint8_t frac_nb = 0;
362  uint8_t digit = 0;
363  uint8_t x = 0, y = 0, z = 0;
364 
365  uint16_t i_dec = 0;
366  uint16_t i_frac = 0;
367 
368  char to_asc[10] = {48,48,48,48,48,48,48,48,48,48};
369 
370  // Clear the osd string.
371  for (x=0; x < sizeof(osd_string); x++) {
372  osd_string[x] = 0;
373  }
374  x = 0;
375  // Search for the prameter start and stop positions.
376  while (*(string+x) != '\0'){
377  if (*(string+x) == '%'){
378  param_start = x;
379  }
380  else
381  if (*(string+x) == 'f') {
382  param_end = x;
383  break;
384  }
385  x++;
386  }
387  // find and bound the precision specified.
388  frac_nb = *(string+param_end-1) - 48; // Convert to number, ASCII 48 = '0'
389  if(frac_nb > 3) {
390  frac_nb = 3; // Bound value.
391  }
392  y = (sizeof(to_asc)- 1); // Point y to the end of the array.
393  i_dec = abs((int16_t)value);
394  // Fist we will deal with the fractional part if specified.
395  if (frac_nb > 0 && frac_nb <= 3) {
396  i_frac = abs((int16_t)((value - (int16_t)value) * 1000)); // Max precision is 3 digits.
397  x = 100;
398  z = frac_nb;
399  do { // Example if frac_nb=2 then 952 will show as .95
400  z--;
401  digit = (i_frac / x);
402  to_asc[y+z] = digit + 48; // Convert to ASCII
403  i_frac -= digit * x; // Calculate the remainder.
404  x /= 10; // 952-(9*100) = 52, 52-(10*5)=2 etc.
405  } while(z > 0);
406  y -= frac_nb; // set y to point where the dot must be placed.
407  to_asc[y] = '.';
408  y--; // Set y to point where the rest of the numbers must be written.
409  }
410 
411  // Now it is time for the integer part. "y" already points to the position just before the dot.
412  do {
413  to_asc[y] = (i_dec % 10) + 48; //Write at least one digit even if value is zero.
414  i_dec /= 10;
415  if (i_dec <= 0) { // This way the leading zero is ommited.
416  if(value < 0) {
417  y--; to_asc[y] = '-'; // Place the minus sign if needed.
418  }
419  break;
420  }
421  else
422  y--;
423  } while(1);
424 
425  // Fill the buffer with the characters in the beggining of the string if any.
426  for (x=0; x<param_start; x++) {
427  *(buffer+x) = *(string+x);
428  }
429 
430  // x is now pointing to the next character in osd_string.
431  // y is already pointing to the first digit or negative sign in "to_asc" array.
432  while (y < sizeof(to_asc)) {
433  *(buffer + x) = to_asc[y];
434  x++; y++;
435  }
436  // x is now pointing to the next character in osd_string.
437  // "param_end" is pointing to the last format character in the string.
438  do {
439  param_end++;
440  *(buffer + x++) = *(string+param_end);
441  } while(*(string+param_end) != '\0'); //Write the rest of the string including the terminating char.
442 
443  return(0);
444 }
max7456_osd_status_codes
Definition: max7456.c:69
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:152
unsigned short uint16_t
Definition: types.h:16
char osd_char
Definition: max7456.c:64
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:149
char osd_str_buf[OSD_STRING_SIZE]
Definition: max7456.c:63
uint8_t input_length
number of data words to read
Definition: spi.h:145
#define OSD_BLINK_CHAR
Definition: max7456_regs.h:24
uint16_t value
Definition: adc_arch.c:585
float h_speed_dir_f
Direction of horizontal ground speed.
Definition: state.h:316
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:150
#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:94
float h_speed_norm_f
Norm of horizontal ground speed.
Definition: state.h:310
uint16_t vsupply
supply voltage in decivolts
Definition: electrical.h:48
osd_attributes
Definition: max7456.c:83
#define OSD_DMM_REG
Definition: max7456_regs.h:7
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:143
#define OSD_DMAH_REG
Definition: max7456_regs.h:8
unsigned char buffer[4096]
Definition: ahrs_ardrone2.c:47
#define OSD_IMAGE_ENABLE
Definition: max7456_regs.h:19
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
#define OSD_RESET
Definition: max7456_regs.h:21
#define FALSE
Definition: imu_chimu.h:141
#define osd_sprintf
Definition: max7456.c:52
enum SPITransactionStatus status
Definition: spi.h:156
Architecture independent SPI (Serial Peripheral Interface) API.
#define OSD_AUTO_INCREMENT_MODE
Definition: max7456_regs.h:27
void max7456_event(void)
Definition: max7456.c:202
uint8_t osd_stat_reg
Definition: max7456.c:91
#define OSD_OSDBL_REG_R
Definition: max7456_regs.h:12
#define OSD_OSDBL_REG
Definition: max7456_regs.h:11
struct spi_transaction max7456_trans
Definition: max7456.c:58
Definition: spi.h:84
Interface for electrical status: supply voltage, current, battery status, etc.
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:153
bool_t spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit a spi transaction.
Definition: spi_arch.c:470
Architecture independent timing functions.
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
char osd_string[OSD_STRING_SIZE]
Definition: max7456.c:62
signed short int16_t
Definition: types.h:17
uint8_t output_length
number of data words to write
Definition: spi.h:146
uint8_t osd_attr
Definition: max7456.c:67
CPOL = 0.
Definition: spi.h:77
uint8_t step
Definition: max7456.c:65
static bool_t _osd_sprintf(char *buffer, char *string, float value)
Definition: max7456.c:357
Definition: max7456.c:85
#define OSD_DMAL_REG
Definition: max7456_regs.h:9
#define OSD_VM0_REG
Definition: max7456_regs.h:5
uint8_t max7456_osd_status
Definition: max7456.c:88
#define TRUE
Definition: imu_chimu.h:144
#define OSD_INVERT_PIXELS
Definition: max7456_regs.h:25
static void osd_put_s(char *string, uint8_t attributes, uint8_t char_nb, uint8_t row, uint8_t column)
Definition: max7456.c:314
#define OSD_VIDEO_MODE_PAL
Definition: max7456_regs.h:16
unsigned char uint8_t
Definition: types.h:14
API to get/set the generic vehicle states.
void max7456_periodic(void)
Definition: max7456.c:117
static struct EnuCoor_f * stateGetSpeedEnu_f(void)
Get ground speed in local ENU coordinates (float).
Definition: state.h:840
CPHA = 0.
Definition: spi.h:68
#define OSD_STRING_SIZE
Definition: max7456.c:51
uint8_t osd_enable_val
Definition: max7456.c:90
slave is selected before transaction and unselected after
Definition: spi.h:57
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:147
uint8_t osd_spi_tx_buffer[2]
Definition: max7456.c:60
Definition: spi.h:119
arch independent LED (Light Emitting Diodes) API
bool_t osd_stat_reg_valid
Definition: max7456.c:92
uint8_t osd_enable
Definition: max7456.c:89
struct Electrical electrical
SPI transaction structure.
Definition: spi.h:142
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
uint16_t osd_char_address
Definition: max7456.c:66
Definition: max7456.c:84
uint8_t osd_spi_rx_buffer[2]
Definition: max7456.c:61
SPICallback before_cb
NULL or function called before the transaction.
Definition: spi.h:154
struct State state
Definition: state.c:36
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:155
static char ascii_to_osd_c(char c)
Definition: max7456.c:274