Subversion Repositories Projects

Rev

Rev 1465 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
1465 - 1
 
2
/****************************************************************/
3
/*                                                                                                                                                                                                                                                      */
4
/*                                                                       NG-Video 5,8GHz                                                                                                                */
5
/*                                                                                                                                                                                                                                                      */
6
/*                                              Copyright (C) 2011 - gebad                                                                                              */
7
/*                                                                                                                                                                                                                                                      */
8
/*      This code is distributed under the GNU Public License                           */
9
/*      which can be found at http://www.gnu.org/licenses/gpl.txt               */
10
/*                                                                                                                                                                                                                                                      */
11
/****************************************************************/
12
 
13
#include <avr/io.h>
14
#include <stdlib.h>
15
#include <string.h>
16
#include <avr/interrupt.h>
17
#include <avr/eeprom.h>
18
#include <util/delay.h>
19
 
20
#include "config.h"
21
#include "dogm.h"
22
#include "messages.h"
23
#include "ngvideo.h"
24
#include "menue.h"
25
#include "servo.h"
26
#include "tools.h"
27
#include "keys.h"
28
#include "usart.h"
29
#include "tracking.h"
30
 
31
// LCD selbst definierte Sonderzeichen, RSSI-Balken und wi232 Empfang Daten im Flash 
32
// deshalb in dogm.c lcdPutc(pgm_read_byte(&lcdChr[i]));
33
SpecialChr_t lcdSpecialChr[7] PROGMEM = {{32,32,16,16,16,16,32,32},
34
                                                                                                                                                                        {32,32,24,24,24,24,32,32},
35
                                                                                                                                                                        {32,32,28,28,28,28,32,32},
36
                                                                                                                                                                        {32,32,30,30,30,30,32,32},
37
                                                                                                                                                                        {32,32,31,31,31,31,32,32},
38
                                                                                                                                                                        {6,8,20,19,20,8,6,32},
39
                                                                                                                                                                        {4,10,32,14,4,4,14,32}};                // Antenne und Imax
40
 
41
SpecialChr_t lcdSpecialChrLs[8] PROGMEM =       {{32,1,1,1,1,1,1,32},
42
                                                                                                                                                                                {32,31,1,1,1,1,31,32},
43
                                                                                                                                                                                {32,31,3,3,3,3,31,32},
44
                                                                                                                                                                                {32,31,7,7,7,7,31,32},
45
                                                                                                                                                                                {32,31,15,15,15,15,31,32},
46
                                                                                                                                                                                {32,31,31,31,31,31,31,32},
47
                                                                                                                                                                                {32,16,16,16,16,16,16,32},
48
                                                                                                                                                                                {32,31,32,32,32,32,31,32}};
49
 
50
SpecialChr_t lcdSpecialChrRs[5] PROGMEM =       {{32,1,1,1,1,1,1,32},
51
                                                                                                                                                                                {32,31,16,16,16,16,31,32},
52
                                                                                                                                                                                {32,31,24,24,24,24,31,32},
53
                                                                                                                                                                                {32,31,28,28,28,28,31,32},
54
                                                                                                                                                                                {32,31,30,30,30,30,31,32}};
55
 
56
/**************************************************************/
57
/*                                                                                                                                                                                                                                              */
58
/*                                                                                                      EEPROM                                                                                                          */
59
/*                                                                                                                                                                                                                                              */
60
/**************************************************************/
61
uint8_t                         ep_eep_init                                                                     EEPROM;
62
char                                    ep_version[sizeof(VERSION)]             EEPROM;
63
uint8_t                         ep_dogm_vers                                                                    EEPROM;
64
uint8_t                         ep_contrast                                                                     EEPROM;
65
uint8_t                         ep_light_time                                                                   EEPROM;
66
uint8_t                         ep_u_offset                                                                     EEPROM;
67
uint16_t                        ep_u_min                                                                                        EEPROM;
68
uint8_t                         ep_channel                                                                              EEPROM;
69
uint8_t                         ep_av_source                                                                    EEPROM;
70
uint8_t                         ep_language                                                                             EEPROM;
71
udbm_t                          ep_udbm[CHANNEL_MAX]                                    EEPROM;
72
uint8_t                         ep_sIdxSteps                                                                    EEPROM;
73
servo_t                         ep_servo[SERVO_NUM_CHANNELS]    EEPROM;
74
uint8_t                         ep_servo_frame                                                          EEPROM;
75
uint8_t                         ep_servo_nr                                                                             EEPROM;
76
uint8_t                         ep_single_step                                                          EEPROM;
77
uint8_t                         ep_repeat                                                                                       EEPROM;
78
uint8_t                         ep_pause                                                                                        EEPROM;
79
uint8_t                         ep_pause_step                                                                   EEPROM;
80
uint8_t                         ep_tracking                                                                             EEPROM;
81
uint8_t                         ep_track_hyst                                                                   EEPROM;
82
uint8_t                         ep_track_tx                                                                             EEPROM;
83
uint8_t                         ep_baudrate                                                                             EEPROM;
84
mk_current_t    ep_mk_current                                                                   EEPROM;
85
uint8_t                         ep_mk_akku_nr                                                                   EEPROM;
86
mk_lipo_t               ep_mk_lipo[AKKU_NR_MAX+1]                       EEPROM;
87
uint8_t                         ep_mk_i_offset                                                          EEPROM;
88
uint8_t                         ep_mk_i_faktor                                                          EEPROM;
89
uint8_t                         ep_mk_w_faktor                                                          EEPROM;
90
 
91
/**************************************************************/
92
// Working variables of EEPROM contents
93
uint8_t                         dogm_vers;
94
uint8_t                         contrast;
95
uint8_t                         light_time = BACKGR_LIGHT_MAX;
96
uint8_t                         backgr_light = OFF;
97
uint8_t                         u_offset = U_OFFSET;
98
uint16_t                        u_min = U_MIN;
99
uint8_t                         channel = CHANNEL;
100
uint8_t                         av_source = AV_SOURCE;
101
uint8_t                         language = NO_LANGUAGE;
102
udbm_t                          udbm = {UDBM_MIN, UDBM_MAX, UDBM_KORR_FA, UDBM_KORR_FA};
103
uint16_t                        hyst_u_min;
104
servo_t                         servo[SERVO_NUM_CHANNELS] =     {{SERVO_REV, SERVO_I0_RIGHT, SERVO_I0_LEFT, SERVO_I0_MIDDLE},\
105
                                                                                                                                                                         {SERVO_REV, SERVO_I0_RIGHT, SERVO_I0_LEFT, SERVO_I0_MIDDLE}};
106
uint8_t                         servo_frame = SERVO_PERIODE;
107
uint8_t                         single_step = SINGLE_STEP;
108
uint8_t                         repeat = REPEAT;
109
uint8_t                         pause = PAUSE;
110
uint8_t                         pause_step = PAUSE_STEP;
111
uint8_t                         baudrate = BAUDRATE;
112
 
113
/**************************************************************/
114
uint8_t                         coldstart;                                      // Flag erstmaliger MK-Start(Motore) nur nach GPS-Fix
115
uint8_t                         ch_stored;                                      // Flag zur Speicherung, wenn Wert im Hauptdisplay geändert
116
 
117
uint8_t                         gps_display = 0;
118
uint8_t                         gps_disp_clear;
119
 
120
uint16_t                        bar_udbm[12];                           // RSSI-Bargraph
121
uint8_t                         wudbm;                                                  // Differenz/Abstand benachbarter udbm[i] für differenzierteren Bargraphen
122
uint8_t                         bat_low = 0;
123
uint8_t                         sw_avx;                                                 // steuert über Set_AV_Source() oder rssi_diversity(av_source) Marker-Position und RX-Umschaltung 
124
uint8_t                         mux_X;                                                  // berücksichtigt Schaltung auf Grund Synchronisation und RSSI (sw_avx meist RSSI) RX-Zählung
125
uint8_t                         MK_Motor_run = 0;               // Flag für RX Time-Counter Start/Stop
126
uint8_t                         mk_timer = 0;                           // Zeitzähler lipo.time_on auf aus
127
 
128
const uint16_t PROGMEM          baud[8] = {4800, 7200, 9600, 14400, 19200, 38400, 57600};
129
 
130
volatile uint8_t        vsync0;
131
volatile uint8_t        vsync1;
132
volatile uint8_t        vscount0;
133
volatile uint8_t        vscount1;
134
volatile uint32_t rxcount0 = 0;
135
volatile uint32_t rxcount1 = 0;
136
 
137
 
138
/************************************************************************************/
139
/*      initialisiert den EEPROM mit default Werten, bzw. liest EEPROM gespeicherte                     */
140
/*      Werte in gloabale Variablen.                                                                                                                                                                                                            */
141
/*      Parameter:                                                                                                                                                                                                                                                                                      */
142
/*      uint8_t ep_reset         :0 = zwangsweises Rückstetzen auf default-Werte                                                        */
143
/*                                                                                                                                                                                                                                                                                                                                      */
144
/************************************************************************************/
145
void Init_EEPROM(uint8_t ep_reset)
146
{ char ver[sizeof(VERSION)];
147
        uint8_t eep_init;
148
 
149
        eep_init = eeprom_read_byte(&ep_eep_init);
150
        eeprom_read_block(&ver, &ep_version, sizeof(VERSION));
151
        _delay_ms(1);
152
 
153
        if ((eep_init != EEP_INITB) || (ep_reset == 0) || strcmp(VERSION, ver))
154
        {
155
                 // nur bei Erstinitialisierung DOGM auf default 3,3V setzen
156
                if ((eep_init != EEP_INITB) || strcmp(VERSION, ver)){
157
                        eeprom_write_byte(&ep_eep_init, EEP_INITB);
158
                        eeprom_write_byte(&ep_dogm_vers, DOGM3V);
159
                        eeprom_write_byte(&ep_contrast, CONTRAST3V);
160
                        eeprom_write_block(&VERSION, &ep_version, sizeof(VERSION));
161
                }
162
                eeprom_write_byte(&ep_light_time, BACKGR_LIGHT_MAX);
163
                eeprom_write_byte(&ep_u_offset, U_OFFSET);
164
                eeprom_write_word(&ep_u_min, U_MIN);
165
                eeprom_write_byte(&ep_channel, CHANNEL);
166
                eeprom_write_byte(&ep_av_source, AV_SOURCE);
167
                eeprom_write_byte(&ep_language, NO_LANGUAGE);
168
                for (uint8_t i = 0; i < CHANNEL_MAX; i++)
169
                        eeprom_write_block(&udbm,&ep_udbm[i],sizeof(udbm_t));
170
                eeprom_write_byte(&ep_sIdxSteps, STEPS_255);
171
                eeprom_write_block(&servo[0],&ep_servo[0],sizeof(servo_t));
172
                eeprom_write_block(&servo[1],&ep_servo[1],sizeof(servo_t));
173
                eeprom_write_byte(&ep_servo_frame, SERVO_PERIODE);
174
                eeprom_write_byte(&ep_servo_nr, 0);                                                                     // nur bei Test-Servo
175
                eeprom_write_byte(&ep_single_step, SINGLE_STEP);                // nur bei Test-Servo
176
                eeprom_write_byte(&ep_repeat, REPEAT);                                                  // nur bei Test-Servo
177
                eeprom_write_byte(&ep_pause, PAUSE);                                                            // nur bei Test-Servo
178
                eeprom_write_byte(&ep_pause_step, PAUSE_STEP);                  // nur bei Test-Servo
179
                eeprom_write_byte(&ep_tracking, TRACKING_MIN);
180
                eeprom_write_byte(&ep_track_hyst, TRACKING_HYSTERESE);
181
                eeprom_write_byte(&ep_track_tx, 0);
182
                eeprom_write_byte(&ep_baudrate, BAUDRATE);
183
                eeprom_write_block(&mk_current,&ep_mk_current,sizeof(mk_current_t));
184
                eeprom_write_byte(&ep_mk_akku_nr, AKKU_NR_MIN);
185
                for (uint8_t i = 0; i <= AKKU_NR_MAX; i++)
186
                        eeprom_write_block(&mk_lipo,&ep_mk_lipo[i],sizeof(mk_lipo_t));
187
                eeprom_write_byte(&ep_mk_i_offset, MK_I_OFFSET);
188
                eeprom_write_byte(&ep_mk_i_faktor, MK_I_FAKTOR);
189
                eeprom_write_byte(&ep_mk_w_faktor, MK_W_FAKTOR);
190
                sIdxSteps = STEPS_255;
191
        }
192
        else
193
        {
194
                light_time = eeprom_read_byte(&ep_light_time);
195
                u_offset = eeprom_read_byte(&ep_u_offset);
196
                u_min = eeprom_read_word(&ep_u_min);
197
                channel = eeprom_read_byte(&ep_channel);
198
                av_source = eeprom_read_byte(&ep_av_source);
199
                language = eeprom_read_byte(&ep_language);
200
                sIdxSteps = eeprom_read_byte(&ep_sIdxSteps);
201
                eeprom_read_block(&servo[0],&ep_servo[0],sizeof(servo_t));
202
                eeprom_read_block(&servo[1],&ep_servo[1],sizeof(servo_t));
203
                servo_frame = eeprom_read_byte(&ep_servo_frame);                // nur bei Test-Servo
204
                single_step = eeprom_read_byte(&ep_single_step);                // nur bei Test-Servo
205
                repeat = eeprom_read_byte(&ep_repeat);                                                  // nur bei Test-Servo
206
                pause = eeprom_read_byte(&ep_pause);                                                            // nur bei Test-Servo
207
                pause_step = eeprom_read_byte(&ep_pause_step);                  // nur bei Test-Servo
208
                tracking = eeprom_read_byte(&ep_tracking);
209
                track_hyst = eeprom_read_byte(&ep_track_hyst);
210
                track_tx = eeprom_read_byte(&ep_track_tx);
211
                baudrate = eeprom_read_byte(&ep_baudrate);
212
                eeprom_read_block(&mk_current,&ep_mk_current,sizeof(mk_current_t));
213
                mk_akku_nr = eeprom_read_byte(&ep_mk_akku_nr);
214
                eeprom_read_block(&mk_lipo,&ep_mk_lipo[mk_akku_nr],sizeof(mk_lipo_t));
215
                mk_i_offset = eeprom_read_byte(&ep_mk_i_offset);
216
                mk_i_faktor = eeprom_read_byte(&ep_mk_i_faktor);
217
                mk_w_faktor = eeprom_read_byte(&ep_mk_w_faktor);
218
        }
219
        dogm_vers = eeprom_read_byte(&ep_dogm_vers);
220
        contrast = eeprom_read_byte(&ep_contrast);
221
        hyst_u_min = u_min;
222
        sw_avx = av_source;
223
        for (uint8_t i = 0; i < SERVO_NUM_CHANNELS; i++) {
224
                servoSet_rev(i, servo[i].rev);
225
                servoSet_min(i, servo[i].min);
226
                servoSet_max(i, servo[i].max);
227
                servoSet_mid(i, servo[i].mid);
228
        }
229
        // Vorberechnung von ServoChannels[channel].duty
230
        servoSetDefaultPos();           // Ausgangsstellung beider Servos
231
        coldstart = 1;
232
        USART_Init_Baudrate();
233
        USART_RX_Mode(tracking);
234
        mk_dUsedCapacity = mk_lipo.UsedCapacity;
235
}
236
 
237
void servoSetDefaultPos(void)
238
{
239
        servoSetPosition(SERVO_PAN, ServoSteps()/2);            // Ausgangsstellung SERVO_PAN
240
        servoSetPosition(SERVO_TILT, 0);                                                                // Ausgangsstellung SERVO_TILT
241
}
242
 
243
void USART_Init_Baudrate(void)
244
{
245
        if (tracking == TRACKING_MKCOCKPIT || tracking == TRACKING_NMEA)
246
                USART_Init(getBaud(baudrate));
247
        else
248
                USART_Init(57600);
249
}
250
 
251
/************************************************************************************/
252
/*      setzt Flag für 3,3V oder 5V DOGM                                                                                                                                                                                                */
253
/*      Parameter:                                                                                                                                                                                                                                                                                      */
254
/*      uint8_t dogm            :Version                                                                                                                                                                                                                                */
255
/*                                                                                                                                                                                                                                                                                                                                      */
256
/************************************************************************************/
257
void Set_DOGM_Version(void)
258
{
259
        if(dogm_vers == DOGM5V) {
260
                dogm_vers = DOGM3V;
261
                contrast = CONTRAST3V;
262
        }
263
        else {
264
                dogm_vers = DOGM5V;
265
                contrast = CONTRAST5V;
266
        }
267
        eeprom_write_byte(&ep_dogm_vers, dogm_vers);
268
        eeprom_write_byte(&ep_contrast, contrast);
269
}
270
 
271
/************************************************************************************/
272
/*      setzt den RX-Kanal von 1 bis 7                                                                                                                                                                                                  */
273
/*      Parameter:                                                                                                                                                                                                                                                                                      */
274
/*      uint8_t channel         :Kanal                                                                                                                                                                                                                          */
275
/*                                                                                                                                                                                                                                                                                                                                      */
276
/************************************************************************************/
277
void Set_Channel(uint8_t channel)
278
{ uint8_t tmp;
279
 
280
        channel--;
281
        tmp = channel & 0b00000111;                             // Kanal 1 bis 7 Werte 0 bis 6 setzen
282
        PORTA |= tmp;
283
        PORTB |= tmp;
284
        tmp = channel | 0b11111000;
285
        PORTA &= tmp;
286
        PORTB &= tmp;
287
        wudbm = RSSI_Calc_UdBm(bar_udbm); // Vergleichstabelle für dBm-Balken berechnen
288
}
289
 
290
/************************************************************************************/
291
/*      schaltet den MUX auf AV1 oder AV2 ohne Darstellung und en-/disabled Interrupt           */
292
/*      wird nur in main.c (Initialisierung) und Menü Sourceumschaltung eingesetzt                      */
293
/*      deswegen cli() und sei() nur in Menu_AV_Source(void)                                                                                                            */
294
/*      Parameter:                                                                                                                                                                                                                                                                                      */
295
/*      uint8_t src             :0-AV1, 1-AV2                                                                                                                                                                                                                   */
296
/*                                                                                                                                                                                                                                                                                                                                      */
297
/************************************************************************************/
298
void SetMux0(void) {
299
        SET_MUX_0;
300
        mux_X = 0;              // für Erkennung RX Zeitzähler
301
}
302
 
303
void SetMux1(void) {
304
        SET_MUX_1;
305
        mux_X = 1;              // für Erkennung RX Zeitzähler
306
}
307
 
308
uint8_t Set_AV_Source(uint8_t src)
309
{
310
        switch(src) {
311
                case AV1:                       CLEAR_INT10;            // Interrupt für Sync ausschalten
312
                                                                                SetMux0();
313
                                                                                break;
314
                case AV2:                       CLEAR_INT10;            // Interrupt für Sync ausschalten
315
                                                                                SetMux1();
316
                                                                                break;
317
                case DIVERSITY: SET_INT10;                      // External Interrupt Mask Register ein
318
                                                                                SetMux0();
319
                                                                                break;
320
        }
321
        return(src);
322
}
323
 
324
 
325
/**************************************************************/
326
/*                                                                                                                                                                                                                                              */
327
/*                                                                               LCD-Backlight                                                                                                  */
328
/*                                                                                                                                                                                                                                              */
329
/**************************************************************/
330
 
331
void lcdSet_BackgrLight_Off(void)
332
{
333
        backgr_light = OFF;
334
        lcdBacklightOff();
335
}
336
 
337
void lcd_BackgrLight_On(void)
338
{ // ...&& (light_count < light_time)) ==> sonst wird Beleuchtung laufend wieder eingeschaltet
339
        if ((backgr_light == OFF)  && (light_count < light_time)) {
340
                backgr_light = ON;
341
                lcdBacklightOn();
342
        }
343
}
344
 
345
void lcd_BackgrLight(void)
346
{
347
        if (backgr_light == ON) {                                                                               // nur wenn Beleuchtung an
348
                if (light_time == BACKGR_LIGHT_MIN)                             // Hintergrundbeleuchtung immer aus?
349
                        lcdSet_BackgrLight_Off();
350
                else
351
                        if (light_time < BACKGR_LIGHT_MAX) {            // Hintergrundbeleuchtung immer an?
352
                                cli();
353
                                light_count++;
354
                                sei();
355
                                if (light_count >= light_time) lcdSet_BackgrLight_Off();
356
                        }
357
        }
358
}
359
 
360
/**************************************************************/
361
/*                                                                                                                                                                                                                                              */
362
/*                                                                                                       ADC                                                                                                                    */
363
/*                                                                                                                                                                                                                                              */
364
/*      http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial        */
365
/*                                                                                                                                                                                                                                              */
366
/**************************************************************/
367
 
368
void ADC_Init(void)
369
{
370
        uint16_t result;
371
 
372
        ADMUX = (0<<REFS1) | (1<<REFS0);                                // AVcc als Referenz benutzen, da an AREF 4,8 V
373
        ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0);          // Frequenzvorteiler Prescaler 128
374
        ADCSRA |= (1<<ADEN);                                                                            // ADC aktivieren
375
 
376
        /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
377
                 also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
378
 
379
        ADCSRA |= (1<<ADSC);                                                                            // eine ADC-Wandlung 
380
        while (ADCSRA & (1<<ADSC) ) {}                                  // auf Abschluss der Konvertierung warten
381
        /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
382
                 Wandlung nicht übernommen. */
383
        result = ADCW;
384
}
385
 
386
/* ADC Einzelmessung */
387
uint16_t ADC_Read( uint8_t channel )
388
{
389
        // Kanal waehlen, ohne andere Bits zu beeinflußen
390
        ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
391
        ADCSRA |= (1<<ADSC);                                                                            // eine Wandlung "single conversion"
392
        while (ADCSRA & (1<<ADSC) ) {}                                  // auf Abschluss der Konvertierung warten
393
        return ADCW;                                                                                                            // ADC auslesen und zurückgeben
394
}
395
 
396
/* ADC Mehrfachmessung mit Mittelwertbbildung */
397
adc_avg_t ADC_Read_Avg(uint8_t channel0, uint8_t channel1, uint16_t average )
398
{ adc_avg_t result;
399
        uint32_t u0 = 0;
400
        uint32_t u1 = 0;
401
 
402
        for (uint16_t i = 0; i < average; ++i){
403
                u0 += ADC_Read( channel0 );
404
                u1 += ADC_Read( channel1 );
405
                _delay_ms(1);
406
        }
407
        result.u0 = u0/average;
408
        result.u1 = u1/average;
409
        return(result);
410
}
411
 
412
/**************************************************************/
413
/*                                                                                                                                                                                                                                              */
414
/*                                                                                               Beeper                                                                                                                 */
415
/*                                                                                                                                                                                                                                              */
416
/*      Bei AVR-Studio 5 ist in delay.h                                                                                                         */
417
/*      #define __DELAY_BACKWARD_COMPATIBLE__                                                                                   */
418
/*      zu setzen                                                                                                                                                                                                       */
419
/*                                                                                                                                                                                                                                              */
420
/**************************************************************/
421
 
422
void Beep(uint8_t time)
423
{
424
        PORTB |= (1<<BEEPER);
425
        _delay_ms(time);
426
        PORTB &= ~(1<<BEEPER);
427
}
428
 
429
void Double_Beep(uint8_t time, uint8_t pause)
430
{
431
        Beep(time);
432
        _delay_ms(pause);
433
        Beep(time);
434
}
435
 
436
/**************************************************************/
437
/*                                                                                                                                                                                                                                              */
438
/*                                                                                              U-Batterie                                                                                                      */
439
/*                                                                                                                                                                                                                                              */
440
/**************************************************************/
441
 
442
// uint16_t u, da bei Displ_Fnct[fu_index](val) der größte Wert UBat gleich 16 Bit 
443
void Displ_1Nk(uint16_t u)
444
{
445
        // 4 => 2 Ziffern vor Komma + 1 Komma + eine Ziffer Nachkomma darstellen, 2 Festkomma 
446
        lcdPuts(my_itoa(u,4,2,1));
447
}
448
 
449
void Displ_U_2Nk(uint16_t u)
450
{
451
        lcdPuts(my_itoa(u,5,2,2));
452
        lcdPutc('V');
453
}
454
 
455
// uint8_t beep_timer :Akku-leer-Beeper nur mit Task_0_1()-Intervalle bei Menü-Rücksprung
456
uint16_t U_Messen_cmp(uint8_t beep_timer)
457
{ uint16_t ubat;
458
        static struct
459
        { uint8_t time;
460
                uint8_t count;
461
        } beep_low;
462
 
463
/* ubat = ((ADC_Read(VBAT) * Vref * (R104 + R103)) /(1024 * R103)) + UD10 (UD10 ist Offset)
464
         Verhältniswert * 100 *8192 ( Verhältniswert = realer Korrekturwert;
465
         mal 100 da alle Werte 2 Nachkommastellen berücksichtigt, aber ohne gerechnet wird
466
         mal 8192 => ohne Bruch gerechnet aber dabei mehr Kommastellen berücksichtigt) */
467
        ubat = (ADC_Read(VBAT) * (uint64_t)43504 + (uint64_t)u_offset * 8192)/ 8192;
468
        if ( ubat <= hyst_u_min )
469
        {
470
                if (!bat_low) {                                                 // nicht laufend Display neu schreiben
471
                        hyst_u_min = u_min + 20;        // 200mV Hysterese - beruhigt Anzeige
472
                        if (tracking == TRACKING_GPS)
473
                                store_LipoData();                               // wenigstens von GPS-Statisik UsedCapacity, time_on usw. speichern
474
                        lcdClear();
475
                        lcdPuts(Msg(MSG_ACCU_LOW));
476
                        bat_low = 1;
477
                        Beep(BEEPBAT);
478
                        // da derzeit Fkt. aller 500ms aufgerufen, mit 2 Min Abstand beginnen
479
                        beep_low.time = BEEP_LOW_TIME;
480
                        beep_low.count = 0;
481
                }
482
                // Akku leer, in immer kürzeren Intervallen Beep
483
                if ((beep_timer == 1) && (beep_low.count++ >= beep_low.time)){
484
                        Beep(BEEPBAT);
485
                        if (beep_low.time > 2)
486
                                beep_low.time /= 2;
487
                        beep_low.count = 0;
488
                }
489
        }
490
        else {
491
                if (hyst_u_min > u_min) {               // falls Anzeige von Batterie leer
492
                        bat_low = 0;                                                    // und zurück geschaltet wird,
493
                        hyst_u_min = u_min;                             // dann Main_Disp wieder darstellen
494
                        Displ_Main_Disp();
495
                }
496
        }
497
        return(ubat);
498
}
499
 
500
void Displ_VBat(void)                                           // da u_offset globale Variable
501
{ uint16_t ubat;
502
 
503
        ubat = U_Messen_cmp(ENABLE_BTIMER);
504
        if (!bat_low) {                                                         // würde sonst Anzeige Akku leer überschreiben
505
                lcdGotoXY(11, 0);
506
                Displ_1Nk(ubat);
507
        }
508
}
509
 
510
 
511
/**************************************************************/
512
/*                                                                                                                                                                                                                                              */
513
/*                                                                                                      RSSI                                                                                                                    */
514
/*                                                                                                                                                                                                                                              */
515
/**************************************************************/
516
 
517
/* RSSI Werte Korrekturfaktor berechnen */
518
uint16_t        RSSI_Calc_Korr(uint8_t nchannel, uint16_t u0, uint16_t u1)
519
{ uint16_t u_max;
520
 
521
        // immer nur den kleineren Wert vergrößern
522
        if (u0 < u1) {
523
                udbm.korr_1 = (((uint32_t)u1 * UDBM_KORR_FA) / u0);             // nur mit Integer und 2 Nachkommastellen rechnen
524
                udbm.korr_2 = UDBM_KORR_FA;
525
                u_max = u1;
526
        }
527
        else {
528
                udbm.korr_2 = (((uint32_t)u0 * UDBM_KORR_FA) / u1);             // nur mit Integer und 2 Nachkommastellen rechnen
529
                udbm.korr_1 = UDBM_KORR_FA;
530
                u_max = u0;
531
        }
532
        eeprom_write_word(&ep_udbm[nchannel - 1].korr_1, udbm.korr_1);
533
        eeprom_write_word(&ep_udbm[nchannel - 1].korr_2, udbm.korr_2);
534
        return(u_max);
535
}
536
 
537
void Displ_Calibr_Aktiv(uint8_t nchannel)
538
{ char str[LCD_COLS + 1];
539
        uint8_t l;
540
        uint8_t zle = 1;
541
 
542
        // Anzeige für nur einen Kanal oder wenn in Schleife, Kanalnr. des z.Z. kalbrierenden Kanals
543
        lcdClear();
544
        lcdPutStrMid(Msg(MSG_CALIBRATION),0);
545
        if (nchannel > 0) {                                     // Anzeige aller RX-Kanäle min. kalibrieren?
546
                strcpy(str, Msg(MSG_RX_CHANNEL));
547
                strcat(str, ": ");
548
                l = strlen(str);
549
                str[l] = nchannel + 0x30;               // gerade zu kalibrierender Kanal, String zusammen stellen
550
                str[++l] = '\0';
551
                lcdPutStrMid(str,1);
552
                zle = 2;
553
        }
554
        lcdPutStrMid(Msg(MSG_RUNNING),zle);
555
}
556
 
557
void Displ_Error_TX(uint8_t message)
558
{
559
        lcdClear();
560
        lcdPutStrMid(Msg(MSG_ERROR), 0);
561
        lcdPutStrMid(Msg(MSG_TX_NOT), 1);
562
        lcdPutStrMid(Msg(message), 2);
563
        delay_ms100x(30);
564
}
565
 
566
uint8_t RSSI_Min_Calibrate(uint8_t nchannel, uint16_t *pbar_udbm)
567
{ adc_avg_t rssi_avg;
568
        uint16_t udbm_min;
569
        uint8_t one_channel = !nchannel;
570
 
571
        Displ_Calibr_Aktiv(nchannel);
572
        if (one_channel) nchannel = channel;
573
        rssi_avg = ADC_Read_Avg(RSSI0, RSSI1, 1000 ); //1000 Wiederholungen mit Mittelwertbildung
574
        // Plausibilitätsprüfung ob Sender ausgeschaltet
575
        if (rssi_avg.u0 + rssi_avg.u1 > 500) {
576
                udbm_min = RSSI_Calc_Korr(nchannel, rssi_avg.u0, rssi_avg.u1); // ist real die größere Spannung, aber der kleinere dbm Wert
577
                eeprom_write_word(&ep_udbm[nchannel - 1].min, udbm_min);
578
                if (one_channel) {
579
                        Double_Beep(DBEEPWR, DBEEPWRP);
580
                        wudbm = RSSI_Calc_UdBm(pbar_udbm);
581
                }
582
        }
583
        else
584
                if (one_channel)
585
                        Displ_Error_TX(MSG_TX_OFF);
586
                else
587
                        return(0);              // Fehleranzeige wird in menue.c gesammelt ausgewertet
588
        return(1);                              // kein Fehler, da bei einen Kanal bereits Fehler angezeigt wurde
589
}
590
 
591
void RSSI_Max_Calibrate(uint16_t *pbar_udbm)
592
{ adc_avg_t rssi_avg;
593
        uint16_t udbm_max;
594
 
595
        Displ_Calibr_Aktiv(0);
596
        rssi_avg = ADC_Read_Avg(RSSI0, RSSI1, 1000 ); //1000 Wiederholungen mit Mittelwertbildung
597
        // Plausibilitätsprüfung ob Sender in der Nähe eingeschaltet
598
        if (rssi_avg.u0 + rssi_avg.u1 < 400) {
599
                udbm_max = RSSI_Calc_Korr(channel, rssi_avg.u0, rssi_avg.u1); // ist real die kleinere Spannung, aber der größere dbm Wert
600
                eeprom_write_word(&ep_udbm[channel - 1].max, udbm_max);
601
                Double_Beep(DBEEPWR, DBEEPWRP);
602
                wudbm = RSSI_Calc_UdBm(pbar_udbm);
603
        }
604
        else Displ_Error_TX(MSG_TX_ON);
605
}
606
 
607
// Vergleichstabelle für RSSI-Bargraph berechnen, vermeidet laufend gleiche Berechnung
608
uint8_t RSSI_Calc_UdBm(uint16_t *pbar_udbm)
609
{ uint8_t n;
610
 
611
        eeprom_read_block(&udbm,&ep_udbm[channel - 1],sizeof(udbm_t));
612
        // -15 um Ende dBm Skala sicher zu erreichen; ohne verfeinerten Bahrgraph war Wert -3
613
        n = (udbm.min - udbm.max -15)/11;
614
        for (uint8_t i = 0; i < 12; i++)
615
                pbar_udbm[i] = (udbm.min - i * n);
616
        return(n / 5); // da 5 Pixel Breite pro Display-Zeichen; Anzeigebalken pro Pixel differenzieren
617
}
618
 
619
void Displ_RSSI_Bargraph(uint16_t *pbar_udbm, uint8_t wudbm, uint16_t uadc)
620
{ char charBar[12];
621
        uint8_t i;
622
        int8_t lz = 11;
623
        char b = 4;
624
 
625
        // Balken zeichnen - udbm
626
        for (i = 0; i < 12; i++) {
627
                if ((b != ' ') && (uadc > pbar_udbm[i])) {
628
                        b       = ' ';
629
                        lz = i - 1;
630
                }
631
                charBar[i] = b;
632
        }
633
        if (lz >= 0) {
634
                charBar[lz] = (pbar_udbm[lz] - uadc) / wudbm ;// Anzeigebalken pro Pixel-"Breite" differenzieren
635
                // bei Teilung 4 wäre richtig und keine Korr. erforderlich, so aber gleichmäßigerer Balkenverlauf
636
                if (charBar[lz] > 4) charBar[lz] = 4;
637
        }
638
        for (i = 0; i < 12; i++)// lcdPuts (ist auch for) funktioniert hier nicht, da Char'\0' für Zeichen auch Stringende
639
                lcdPutc(charBar[i]);
640
}
641
 
642
uint8_t RSSI_Diversity(uint8_t src, uint16_t *pbar_udbm, uint8_t visible)
643
{ uint16_t u0, u1;
644
        static uint8_t div_flag, ret_div_flag;
645
        char marker;
646
 
647
        u0 = (ADC_Read(RSSI0) * (uint32_t)udbm.korr_1)/UDBM_KORR_FA;
648
        u1 = (ADC_Read(RSSI1) * (uint32_t)udbm.korr_2)/UDBM_KORR_FA;
649
 
650
        // falls beide RX gleich gut/schlecht synchronisieren
651
        // Achtung! Niedrigere Spannung - größere Feldstärke
652
        if (src == DIVERSITY) {
653
                if (u0 < u1) {
654
                        ret_div_flag = AV1;
655
                        if ((vscount0 == 255) && (vscount1 == 255)) SetMux0();          // egal wann RSSI schaltet ==> es ist kein sync vorhanden
656
                }
657
                else {
658
                        ret_div_flag = AV2;
659
                        if ((vscount0 == 255) && (vscount1 == 255)) SetMux1();          // egal wann RSSI schaltet ==> es ist kein sync vorhanden
660
                }
661
        }
662
        else ret_div_flag = src; // sonst leerer Returnwert
663
 
664
        if (visible) {
665
                if (src == DIVERSITY) {
666
                        // Synchronisation vorrangig zur Feldstärke
667
                        if ((vsync0 != vsync1) && ((vscount0 & vscount1) < 255)) {
668
                                // ist nur zur Anzeige - Sync-MUX wird über Interrupt gesteuert
669
                                div_flag = vsync0 == 0? AV1: AV2;
670
                                marker = MARKER_SYNC;
671
                        }
672
                        else {
673
                                div_flag = ret_div_flag;
674
                                marker = MARKER_RSSI;
675
                        }
676
                }
677
                else marker = MARKER_AV;
678
                // wäre unschön - keine RSSI-Anzeige, aber Marker springt
679
                if ((u0 > pbar_udbm[0]) && (u1 > pbar_udbm[0])) marker = ' ';
680
                lcdGotoXY(2, 1);
681
                Displ_RSSI_Bargraph(pbar_udbm, wudbm, u0);
682
                lcdGotoXY(2, 2);
683
                Displ_RSSI_Bargraph(pbar_udbm, wudbm, u1);
684
                if (src == DIVERSITY) Displ_AV_Mark(div_flag, marker);
685
        }
686
        return(ret_div_flag);
687
}
688
 
689
/**************************************************************/
690
/*                                                                                                                                                                                                                                              */
691
/*                      Diversity v-Synchronisation Interruptroutinen                                   */
692
/*                                                                                                                                                                                                                                              */
693
/**************************************************************/
694
 
695
/* Impulszähler für V-Synchronisation 0 und 1
696
         wird durch Interrupt des jewiligen vSync einzeln zurückgesetzt. 8-bit Timer*/
697
ISR(TIMER2_OVF_vect)
698
{
699
        TCNT2 = (int8_t)(int16_t)-(F_CPU / 64 * 500e-6);        // preload
700
        if (vscount0 < 255) ++vscount0; // Überlauf von vscount vermeiden
701
        if (vscount1 < 255) ++vscount1; // Überlauf von vscount vermeiden
702
        if (rx_timeout < RX_TIME_END) ++rx_timeout; // veranlasst bei GPS-Tracking MK Datensatz senden
703
        if ((mk_timer) && (mk_lipo.time_on < T2PROD_M59S59)) ++mk_lipo.time_on; // T2PRODM59S59 = 3599 * 4000
704
        if (((tracking == TRACKING_GPS) && (MK_Motor_run)) || ((tracking == TRACKING_NMEA) && !coldstart)) { // MK-Motoren müssen laufen
705
                if (mux_X)
706
                        rxcount1++;             // kein Test auf Überlauf ==> Counter groß genug - bis Stunden
707
                else
708
                        rxcount0++;
709
        }
710
}
711
 
712
/* Messung von Impulsabstand v-Synchronisation 0
713
         Zur Vermeidung von Bildstörunen erfolgt MUX-Umschaltung in Bildaustastung */
714
ISR(INT0_vect)
715
{
716
        if ((vscount0 >= 79) && (vscount0 <= 81)) {
717
                vsync0 = 0;
718
                if ((mux_X) && (vscount1 == 255)) {
719
                  SetMux0();
720
                        vsync1 = 1;
721
                }
722
        }
723
        else {
724
                vsync0 = 1;
725
                if (vsync1 == 0)
726
                        SetMux1();
727
        }
728
        if (vsync0 == vsync1) { //nur wenn vSynchronisation gleich gut/schlecht ist greift RSSI 
729
                if (sw_avx == AV1) {
730
                        SetMux0();
731
                }
732
                else
733
                        SetMux1();
734
        }
735
        vscount0 = 0;
736
}
737
 
738
/* Messung von Impulsabstand v-Synchronisation 1
739
         Zur Vermeidung von Bildstörunen erfolgt MUX-Umschaltung in Bildaustastung */
740
ISR(INT1_vect)
741
{
742
        if ((vscount1 >= 79) && (vscount1 <= 81)) {
743
                vsync1 = 0;
744
                if (!(mux_X) && (vscount0 == 255)) {
745
                                SetMux1();
746
                                vsync0 = 1;
747
                }
748
        }
749
        else {
750
                vsync1 = 1;
751
                if (vsync0 == 0)
752
                        SetMux0();
753
        }
754
        if (vsync0 == vsync1) { //nur wenn vSynchronisation gleich gut/schlecht ist greift RSSI
755
                if (sw_avx == AV1) {
756
                        SetMux0();
757
                }
758
                else
759
                        SetMux1();
760
        }
761
        vscount1 = 0;
762
}
763
 
764
/**************************************************************/
765
/*                                                                                                                                                                                                                                              */
766
/*                                                                                                      Tasks                                                                                                                   */
767
/*              ermöglicht unterschiedliche Zeiten f. UBat, Sync...                     */
768
/*                                                                                                                                                                                                                                              */
769
/**************************************************************/
770
 
771
void Task_0_1(void)
772
{
773
        if (task_timer0_1) {
774
                cli();
775
                task_timer0_1 = 0;
776
                sei();
777
                Displ_VBat();
778
         }
779
 }
780
 
781
void Task_0_2(void)
782
{
783
        if (task_timer0_2) {
784
                cli();
785
                task_timer0_2 = 0;
786
                sei();
787
                sw_avx = RSSI_Diversity(av_source, bar_udbm, !bat_low);
788
        }
789
}
790
 
791
void Task_0_3(void)
792
{
793
        if (task_timer0_3) {
794
                cli();
795
                task_timer0_3 = 0;
796
                sei();
797
                sw_avx = RSSI_Diversity(av_source, bar_udbm, 0);
798
                if (tracking == TRACKING_MKCOCKPIT) Tracking_MKCockpit();
799
        }
800
}
801
 
802
void Task_0_4(void)
803
{
804
        if (task_timer0_4) {
805
                cli();
806
                task_timer0_4 = 0;
807
                sei();
808
                if (tracking == TRACKING_GPS)
809
                        Tracking_GPS();
810
                else if (tracking == TRACKING_NMEA)
811
                        Tracking_NMEA();
812
                if (gps_display == GPS_RX_COUNT) Displ_RX_Time(); // aktualisieren der Empfängerzeiten
813
        }
814
}
815
 
816
void Task_0_5(void)                                     // Nur für Tasten-Beschleunigung/-Wiederholrate! Hintergrund: Rücksetzung.
817
{                                                                                                               // Hintergrund: Rücksetzung. Beginnt nach jeden Tastendruck neu zu zählen.
818
        lcd_BackgrLight_On();                   // muss bei beliebiger Taste sofort eingeschaltet werden
819
        if (task_timer0_5) {
820
                cli();
821
                task_timer0_5 = 0;
822
                sei();
823
                lcd_BackgrLight();
824
        }
825
}
826
 
827
void Tasks_invisible(void)      // wird in main.c und menue.c aufgerufen
828
{
829
        Task_0_3();
830
        Task_0_4();
831
        Task_0_5();
832
        if (tracking == TRACKING_RSSI) Tracking_RSSI();
833
}