// ========================================================================
// Datei:  LP_STEP.CPP                               Version:0.1
// Inhalt: Funktionen zur Steuerung eines Schrittmotors mit der
//	   parallelen Schnittstelle.
//	   Die Funktionen geben nichts am Bildschirm aus und koennen
//	   daher universell verwendet werden. Falls ein Fehler auf-
//	   getreten ist, kann dies anhand der Rueckgabewerte festge-
//	   stellt werden.
//         Die Funktionen arbeiten mit Funktionen der Bibliothek LP_FUNC!
//         und verwenden auch deren Fehlercodes.
//         Die eigenen Fehlercodes von LP_STEP beginnen ab -100.
//
// Autor:  Gerhard Juengling, HTL Wien 4, Sommer 2000
// ========================================================================

#include "lp_func.h"
#include "lp_step.h"
#include <dos.h>
#include <stdio.h>

long lps_position = 0;                  // Motorposition in Schritten
unsigned char lps_initialized =FALSE;	// Flag gibt an, ob lp_func schon initialisiert wurde
int lps_errnumber=-100;                 // Fehlernummer 0.. kein Fehler
unsigned int lps_speed = 50;            // in Schritten / Sekunde
unsigned int lps_delay;                 // Wartezeit je Schritt
char lps_statenumber=0;              // aktueller Zustand des Schrittm.
unsigned char lps_direction=0;          // Richtung (0 oder 1)
unsigned int lps_steps360;              // Anz. der Schritte fuer 360 Grad

// Halbschrittsequenz: (+ pos, - neg, o kein Strom)
// lps_statenumber : 01234567    (0..7)
//          Spule 1: ++o---o+    (X1,Y1)
//          Spule 2: o---o+++    (X2,Y2)
//               X1: 11000001    Bit 0
//               Y1: 00011100        1
//               E1: 00000000        2
//               X2: 00000111        3
//               Y2: 01110000        4
//               E1: 00000000        5
// Annahme fuer die Variable lps_muster:
// X1,Y1,X2,Y2 sind den Datenbits 0,1,3,4 der par. Schnittstelle zugeordnet
#define LPS_MAX_STATE 7
unsigned char lps_pattern[]={0x01,0x11,0x10,0x12,0x02,0x0a,0x08,0x09};
// Muster fuer Vollschrittmodus:
//unsigned char lps_pattern[]={0x01,0x10,0x02,0x08,0x01,0x10,0x02,0x08};
//unsigned char lps_pattern[]={0x11,0x12,0x0a,0x09,0x11,0x12,0x0a,0x09};

// ========================================================================
// lps_init: Initialisiert die Ein-Ausgaberoutinen und alle Variablen.
// Diese Funktion muss aufgerufen werden, da sonst alle anderen Funk-
// tionen eine Fehlermeldung zurueckgeben!
// Aufrufparameter:
//   int lptport: 1,2 oder 3 steht fuer LPT1, LPT2 oder LPT3
//   int steps:   Anzahl der Schritte fuer eine volle Umdrehung
// Rueckgabewert (int): 0  kein Fehler
//			-1 keine parallele Schnittstelle vorhanden *)
//			-2 lp_init wurde schon aufgerufen
//			-3 gewuenschte Schnittstelle nicht vorhanden *)
// ========================================================================

int lps_init(int lptport, unsigned int steps)
{
        lps_setspeed (lps_speed);       // berechnet das aktuelle delay
        lps_initialized = TRUE;
        lps_steps360 = steps;
	return(lp_init(lptport));
}

// ========================================================================
// lps_info, lps_version: Informationen ueber die LP_STEP Bibliothek
// Rueckgabewert (char *): Zeiger auf einen Infostring
// ========================================================================
char *lps_info()
{
    return("LP_STEP: Funktionen zum Steuern von Schrittmotoren   G.Juengling 2000");
}

char *lps_version()
{
    return("LP_STEP Version 1.0, Juli 2000");
}

// ========================================================================
// lps_setspeed: stellt die Geschwindigkeit in Schritten pro Sekunde ein.
// stelle aus.
// Aufrufparameter:
//   float speed: Geschwindigkeit in Schritten je Sekunde (0.2 ... 500)
// Rueckgabewert (int): Fehlercode
// ========================================================================
#define min_speed 0.2
#define max_speed 500.

int lps_setspeed(float speed)
{
	if ((speed >= min_speed) && (speed <= max_speed)) {
            lps_speed = speed;
            lps_delay = 1000/speed;
            return 0;
        }
        else return (-101);
}

// ========================================================================
// lps_on, lps_on: Schaltet die Spannung am Schrittmotor ein bzw. aus
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lps_off()
{
        return(lp_output(0));
}

int lps_on()
{
        return(lp_output(lps_pattern[lps_statenumber]));
}

// ========================================================================
// lps_step: Bewegt sich zu um einen Schritt
// Aufrufparameter:
//   unsigned char richtung: Richtung 0,1
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lps_step(unsigned int richtung)
{
        if (richtung) {
            if (++lps_statenumber>LPS_MAX_STATE) lps_statenumber=0;
            lps_position++;
        }
        else {
            if (--lps_statenumber<0) lps_statenumber=LPS_MAX_STATE;
            lps_position--;
        }
        return(lp_output(lps_pattern[lps_statenumber]));
}

// ========================================================================
// lps_gorelative: Bewegt sich relativ zu einer absoluten Position
// Aufrufparameter:
//   long position: Anzufahrende relative Position (> oder < null)
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lps_gorelative(long position)
{
int i, step,dir;
    if (position == 0L) return (-101);

    step = (position>0 ? 1 : -1);       // Schritt fuer For-Schleife
    dir = (position>0 ? 1 : 0);         // Richtung
    position = position*step;           // anstatt abs()
    for (i=1;i<=position;i++) {
        lps_step(dir);
        delay(lps_delay);               // kleine Pause
    }
    return (lp_status());
}

// ========================================================================
// lps_goabsolut: Bewegt sich zu einer absoluten Position
// Aufrufparameter:
//   long position: Anzufahrende Position
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lps_goabsolut(long position)
{
long delta;
        delta=position - lps_position;
        lps_gorelative(delta);
	return(0);
}

// ========================================================================
// lps_errno: Gibt den Errorcode der letzten lps_Funktion zurueck
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lps_errno()
{
	return (lps_errnumber);
}

// ========================================================================
// lps_errmsg: Retourniert eine Fehlermeldung zum angegebenen Errorcode
// Rueckgabewert (char *): Zeiger auf Fehlermeldung
// ========================================================================
char *lps_errmsg(int number)
{
        if (number>-100) return (lp_errmsg(number));
        else {
          switch (number) {
           case -101:
               return("Falsche Geschwindigkeit");    // noch nicht implementiert
           default:
               return("LPS_ERROR");    // noch nicht implementiert
          }
        }
}

// ========================================================================
// lps_stepper_info: Gibt einen String mit Informationen zum Zustand
//                   des Schrittmotors aus.
// Rueckgabewert (char *): Zeiger auf den Text
// ========================================================================
char *lps_stepper_info()
{
#define ISL 80  // infostring laenge
static char infostring[ISL];
	sprintf(infostring, "LP_STEP: Pos: %6ld, Speed: %3d, Pat: %2x, Dir: %1d",
        lps_position, lps_speed, lps_statenumber, lps_direction);
        return(infostring);
}

// ========================================================================
// lps_sethome: Macht die aktuelle Position zur Home-Position des Schrittmotors
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lps_sethome()
{
        lps_position = 0L;
        return(0);
}

// ========================================================================
// lps_360: Motor dreht sich um 360 Grad
// Rueckgabewert (int): Fehlercode
// ========================================================================
int lps_360(unsigned int richtung)
{
        if (richtung) lps_gorelative(lps_steps360);
        else          lps_gorelative(-lps_steps360);
        return(0);
}

