Subversion Repositories Projects

Rev

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% 
}