Blame |
Last modification |
View Log
| RSS feed
/*****************************************************************************
* Copyright (C) 2008 Thomas Kaiser, thomas@ft-fanpage.de *
* Copyright (C) 2009 Peter "woggle" Mack, mac@denich.net *
* Copyright (C) 2011 Christian "Cebra" Brandtner, brandtner@brandtner.net *
* Copyright (C) 2011 Harald Bongartz *
* Copyright (C) 2012 Martin Runkel *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
* Credits to: *
* Holger Buss & Ingo Busker from mikrokopter.de for the MK project + SVN *
* http://www.mikrokopter.de *
* Gregor "killagreg" Stobrawa for his version of the MK code *
* Thomas Kaiser "thkais" for the original project. See *
* http://www.ft-fanpage.de/mikrokopter/ *
* http://forum.mikrokopter.de/topic-4061-1.html *
* Claas Anders "CaScAdE" Rathje for providing the font and his C-OSD code *
* http://www.mylifesucks.de/oss/c-osd/ *
* Harald Bongartz "HaraldB" for providing his Ideas and Code for usibility*
*****************************************************************************/
#include "cpu.h"
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdlib.h>
#include "lcd.h"
#include "timer.h"
#include "servo.h"
#include "messages.h"
#include "lipo.h"
#include "stick.h"
#define SERVO_CORRECT 3.125
#include <util/delay.h>
#include <inttypes.h>
#include <stdlib.h>
#include "main.h"
#include "uart1.h"
#include "usart.h"
#define LIMIT_MIN_MAX(value, min, max) {if(value <= min) value = min; else if(value >= max) value = max;}
int16_t Pos_Stick
[12]; // 1,5mS
int16_t Pos_alt
[5]; //
uint8_t BalkenPos
= 0;
uint8_t Stick_Display
= 0;
uint8_t serialChannelRichtung
= 0;
uint8_t serialChannelConfig
= 2;
//--------------------------------------------------------------
//
void joystick
(void)
{
// uint8_t chg = 0;
// uint8_t Pos_Stick = 150; // 1,5mS
// uint8_t Pos_alt = 150; //
//int16_t Pos_Stick[12]; // 1,5mS
uint8_t chg
= 0;
//uint8_t BalkenPos = 0;
uint8_t Stick_Nr
= 0;
//uint8_t Stick_Display = 0;
uint8_t i
= 0;
memset (Pos_Stick
, 150, 3); // füllt 3+1 Byte vom Pos_Stick[12] mit 150
//int16_t Pos_alt[5]; //
int16_t Poti_Summe
[5]; //
memset (Poti_Summe
, 0, 5); // füllt 3+1 Byte mit 0
int16_t Poti_Neutral
[5]; //
// ADC- init
Stick_Nr
= 0;
ADMUX
= (1<<REFS0
)|(0<<MUX0
); // Multiplexer selection Register: AVCC with external capacitor at AREF pin , ADC1
ADMUX
= (ADMUX
& ~
(0x1F)) | (Stick_Nr
& 0x1F); // ADC[Stick_Nr] verwenden
timer
= 50;
while (timer
> 0);
ADCSRA
= (1<<ADEN
)|(1<<ADSC
)|(1<<ADPS2
)|(1<<ADPS1
)|(1<<ADPS0
); // ADC Enable, ADC Start, Prescaler 128
// Stick-Neutralposition bestimmen
while (ADCSRA
& (1<<ADSC
)); // wenn ADC fertig
Poti_Neutral
[Stick_Nr
] = ((ADCW
>>2)&0xff);
LIMIT_MIN_MAX
(Poti_Neutral
[Stick_Nr
],108,148);
Stick_Nr
= 2 ;
ADMUX
= (ADMUX
& ~
(0x1F)) | (Stick_Nr
& 0x1F); // ADC[i] verwenden
// Stick_Nr 1,2,3 = Potis, Stick_Nr 1= Lipo
ADCSRA
|= (1<<ADSC
); // ADC Start
while (ADCSRA
& (1<<ADSC
)); // wenn ADC fertig
Poti_Neutral
[Stick_Nr
] = ((ADCW
>>2)&0xff);
LIMIT_MIN_MAX
(Poti_Neutral
[Stick_Nr
],108,148);
Stick_Nr
= 0;
ADMUX
= (ADMUX
& ~
(0x1F)) | (Stick_Nr
& 0x1F); // ADC[i] verwenden
// Stick_Nr 1,2,3 = Potis, Stick_Nr 1= Lipo
ADCSRA
|= (1<<ADSC
); // ADC Start
//OCR1A = 150 * SERVO_CORRECT; // Servomitte
lcd_cls
();
// Kopfzeile und Rahmen zeichnen
lcd_printp
(PSTR
(" serielle Potis 1-5 "), 2);
//lcd_printp_at (7, 5, PSTR("%"), 0);
//lcd_printp_at (16, 5, PSTR("mS"), 0);
lcd_puts_at
(0, 7, strGet
(KEYLINE3
), 0);
lcd_printp_at
(18, 7, PSTR
("\x19O\x18"), 0);
for (i
=0 ; i
< 5 ; i
++)
{
BalkenPos
= 12 + (i
*8) ;
lcd_rect
(3,BalkenPos
, 120, 6, 1); // +-150% Rahmen
lcd_line
(23,BalkenPos
,23,(BalkenPos
+6),1); // -100%
lcd_line
(43,BalkenPos
,43,(BalkenPos
+6),1); // -50%
lcd_frect
(62,BalkenPos
, 2, 6, 1); // 0%
lcd_line
(83,BalkenPos
,83,(BalkenPos
+6),1); // +50%
lcd_line
(103,BalkenPos
,103,(BalkenPos
+6),1); // +100%
}
// Reset auf Mittelstellung
Pos_Stick
[0] = 150;
Poti_Summe
[0] = 0;
Pos_Stick
[2] = 150;
Poti_Summe
[2] = 0;
Pos_Stick
[4] = 150;
Poti_Summe
[4] = 0;
chg
= 255;
do
{
if (!(ADCSRA
& (1<<ADSC
))) // wenn ADC fertig
{
//Pos_Stick[Stick_Nr] = 150 + 128 - ((ADCW>>2)&0xff);
if (serialChannelRichtung
& (1<<Stick_Nr
))
Pos_Stick
[Stick_Nr
] = Poti_Neutral
[Stick_Nr
] - ((ADCW
>>2)&0xff);
else
Pos_Stick
[Stick_Nr
] = ((ADCW
>>2)&0xff) - Poti_Neutral
[Stick_Nr
];
LIMIT_MIN_MAX
(Pos_Stick
[Stick_Nr
],-120,120);
if ((Stick_Nr
==0) || (Stick_Nr
==2)) // nur die Potis 1,2 sind nicht neutralisierend
{
Poti_Summe
[Stick_Nr
] += (Pos_Stick
[Stick_Nr
]/8) * abs(Pos_Stick
[Stick_Nr
]/8);
LIMIT_MIN_MAX
(Poti_Summe
[Stick_Nr
],-(120*128),(120*128));
Pos_Stick
[Stick_Nr
]= Poti_Summe
[Stick_Nr
] / 128; // nicht neutralisierend
}
Pos_Stick
[Stick_Nr
] += 150;
LIMIT_MIN_MAX
(Pos_Stick
[Stick_Nr
],30,270); // war 75 , 225
if (Pos_Stick
[Stick_Nr
] != Pos_alt
[Stick_Nr
]) // nur bei Änderung
{
chg
|= (1<<Stick_Nr
) ;
//Pos_alt=Pos_Stick ; // verschoben
}
Stick_Nr
++ ;
//if (Stick_Nr==1) Stick_Nr=2; // Lipo überspringen
if (Stick_Nr
==3) // Taster
{
// if (get_key_press (1 << KEY_EXT)) Pos_Stick[Stick_Nr] = 225;
if (serialChannelRichtung
& (1<<Stick_Nr
))
{
if (PINA
& (1 << KEY_EXT
)) Pos_Stick
[Stick_Nr
] = 30;
else Pos_Stick
[Stick_Nr
] = 270;
}
else
{
if (PINA
& (1 << KEY_EXT
)) Pos_Stick
[Stick_Nr
] = 270;
else Pos_Stick
[Stick_Nr
] = 30;
}
if (Pos_Stick
[Stick_Nr
] != Pos_alt
[Stick_Nr
])
{
chg
|= (1<<Stick_Nr
) ;
}
Stick_Nr
=0;
}
/*
#ifndef ohne_Lipo // MartinR
Stick_Nr = 1; // MartinR AD-Kanal 1 überspringen wegen Lipo Überwachung
#endif
*/
ADMUX
= (ADMUX
& ~
(0x1F)) | (Stick_Nr
& 0x1F); // ADC[i] verwenden
// Stick_Nr 1,2,3 = Potis, Stick_Nr 0= Lipo
ADCSRA
|= (1<<ADSC
); // ADC Start
//serialPotis ();
}
if ((get_key_press
(1 << KEY_PLUS
) || get_key_long_rpt_sp
((1 << KEY_PLUS
), 3)) && (Pos_Stick
[4] < 271))
{
Pos_Stick
[4] ++ ;
//LIMIT_MIN_MAX (Pos_Stick[Stick_Nr],30,270); // war 75 , 225
chg
|= (1<<4) ;
}
else if ((get_key_press
(1 << KEY_MINUS
) || get_key_long_rpt_sp
((1 << KEY_MINUS
), 3)) && (Pos_Stick
[4] > 29))
{
Pos_Stick
[4] -- ;
//LIMIT_MIN_MAX (Pos_Stick[Stick_Nr],30,270); // war 75 , 225
chg
|= (1<<4) ;
}
else if (get_key_press
(1 << KEY_ENTER
))
{
/*
for (i=0 ; i< 4 ; i++)
{
BalkenPos = 12 + (i*8) ;
lcd_frect (4, (BalkenPos+1), 118, 4, 0); // Balken löschen
lcd_frect(62, BalkenPos, 2, 6, 1); // 0%
}
*/
Pos_Stick
[0] = 150;
Poti_Summe
[0] = 0;
Pos_Stick
[2] = 150;
Poti_Summe
[2] = 0;
Pos_Stick
[4] = 150;
Poti_Summe
[4] = 0;
BeepTime
= 200;
BeepMuster
= 0x0080;
chg
= 255;
}
if (chg
)
{
if (chg
& (1<<0)); // Stick 1
{
BalkenPos
= 12 + (0*8) ;
Stick_Display
= 0;
Balken_Zeichnen
() ;
Pos_alt
[Stick_Display
]=Pos_Stick
[Stick_Display
];
}
// Stick 2 = Lipo
if (chg
& (1<<1)); // Stick 2
{
BalkenPos
= 12 + (1*8) ;
Stick_Display
= 1;
if (serialChannelConfig
& (0<<1)) Balken_Zeichnen
() ; // nur wenn keine Lipo-Spannung
Pos_alt
[Stick_Display
]=Pos_Stick
[Stick_Display
];
}
if (chg
& (1<<2)); // Stick 3
{
BalkenPos
= 12 + (2*8) ;
Stick_Display
= 2;
Balken_Zeichnen
() ;
Pos_alt
[Stick_Display
]=Pos_Stick
[Stick_Display
];
}
if (chg
& (1<<3)); // Stick 4 = Taster
{
BalkenPos
= 12 + (3*8) ;
Stick_Display
= 3;
Balken_Zeichnen
() ;
Pos_alt
[Stick_Display
]=Pos_Stick
[Stick_Display
];
}
if (chg
& (1<<4)); // Stick 5 = Taster vom PKT
{
BalkenPos
= 12 + (4*8) ;
Stick_Display
= 4;
Balken_Zeichnen
() ;
//OCR1A = (((Pos_Stick[Stick_Display]-150)/1.6)+150) * SERVO_CORRECT; // Servostellung , 1.6=0.8*0.5
Pos_alt
[Stick_Display
]=Pos_Stick
[Stick_Display
];
}
chg
= 0;
serialPotis
();
}
}
while (!get_key_press
(1 << KEY_ESC
));
get_key_press
(KEY_ALL
);
#ifdef HWVERSION3_9
#ifndef ohne_Lipo // MartinR
ADC_Init
(); // ADC für Lipomessung wieder aktivieren
#endif
#endif
}
//--------------------------------------------------------------
//
void serialPotis
(void)
{
uint8_t i
= 0;
memset (buffer
, 0, 12); // füllt die 12+1 Byte vom buffer mit 0
for (i
=0 ; i
< 5 ; i
++)
{
buffer
[i
] = Pos_Stick
[i
]-150 ;
}
SendOutData
('y', ADDRESS_FC
, 1, buffer
, 12);
}
//--------------------------------------------------------------
//
void Balken_Zeichnen
(void)
{
// Balken löschen
if ((Pos_Stick
[Stick_Display
] > Pos_alt
[Stick_Display
])&&(Pos_alt
[Stick_Display
] < 150)) // Balken links löschen
lcd_frect
((63-((150 -Pos_alt
[Stick_Display
]) * 0.5)), (BalkenPos
+1), (63-((150- Pos_Stick
[Stick_Display
]) * 0.5)), 4, 0);
if ((Pos_Stick
[Stick_Display
] < Pos_alt
[Stick_Display
])&&(Pos_alt
[Stick_Display
] > 150)) // Balken rechts löschen
lcd_frect
((63+((Pos_Stick
[Stick_Display
] - 150) * 0.5)), (BalkenPos
+1), (63+((Pos_alt
[Stick_Display
] - 150) * 0.5)), 4, 0);
// Balken zeichnen
if (Pos_Stick
[Stick_Display
] >= 150)
{
lcd_frect
(63, (BalkenPos
+1), ((Pos_Stick
[Stick_Display
] - 150) * 0.5), 4, 1);
//write_ndigit_number_u (4, 5, ((Pos_Stick[Stick_Display] - 150) * 1.25), 3, 0, 0); // Pulse width in %
lcd_frect
(62, (BalkenPos
), 2, 6, 1); // 0%
}
else
{
lcd_frect
(63 - ((150 - Pos_Stick
[Stick_Display
]) * 0.5), (BalkenPos
+1), ((150 - Pos_Stick
[Stick_Display
]) * 0.5), 4, 1);
//write_ndigit_number_u (4, 5, ((150 - Pos_Stick[Stick_Display]) * 1.25), 3, 0, 0); // Pulse width in %
lcd_frect
(62, (BalkenPos
), 2, 6, 1); // 0%
}
// Raster zeichnen
lcd_line
(3, BalkenPos
,3, (BalkenPos
+6),1); // -150%
lcd_line
(23, BalkenPos
,23, (BalkenPos
+6),1); // -100%
lcd_line
(43, BalkenPos
,43, (BalkenPos
+6),1); // -50%
lcd_line
(83, BalkenPos
,83, (BalkenPos
+6),1); // +50%
lcd_line
(103,BalkenPos
,103,(BalkenPos
+6),1); // +100%
lcd_line
(123,BalkenPos
,123,(BalkenPos
+6),1); // +150%
}