Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

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