/*
 * Seriale.c
 *
 * Scritto da Antonello Biancalana, ProMIND per Amiga Magazine
 *
*/

#include <exec/types.h>
#include <devices/serial.h>

#ifdef LATTICE

#include <proto/all.h>
#include <stdio.h>

#endif

#define BUFLEN 256      /* lunghezza del buffer dati per lettura */

/* prototipi delle funzioni che utilizzeremo */

int OpenSerial(void);
void CleanUp(void), Send(char *);

struct MsgPort *MyPort;         /* Porta utilizzata per il serial.device */
struct IOExtSer *SerialData;    /* struttura dati per il serial.device   */

BOOL DevOpened=FALSE;   /* Indica lo stato del serial.device */
                        /* =TRUE  : serial.device aperto     */
                        /* =FALSE : serial.device non aperto */ 

main(int argc, char **argv)
{
    BOOL IsEnd=FALSE;
    char buffer[BUFLEN];
    int i;

    printf("Apertura dispositivo seriale\n\n");

    /* Impostiamo ed apriamo il serial.device */

    if(OpenSerial())    /* non è stato possibile aprire il serial.device */
        CleanUp();

    Send("Collegamento effettuato. Immettere comando\n\n");
    
    printf("Attesa messaggio\n\n");

    while(!IsEnd)
    {
        /* Cancelliamo tutti i dati precedentemente letti */

        for(i=0; i<BUFLEN; i++)
            buffer[i]='\0';

        SerialData->IOSer.io_Command=CMD_READ;  /* Comando di lettura dal dispositivo */
        SerialData->IOSer.io_Length=BUFLEN;     /* lunghezza del buffer su cui memorizzare i dati */
        SerialData->IOSer.io_Data=(APTR)buffer; /* indirizzo del buffer dati */

        SendIO((struct IORequest *)SerialData); /* Trasmettiamo al serial.device la */
                                                /* nostra richiesta di lettura dati */
        
        /* Aspettiamo ora che arrivi qualcosa dalla porta seriale */

        Wait(1L<<MyPort->mp_SigBit);

        printf("ricevuto comando %s\n",buffer);

        /* valutazione e riconoscimento dei messaggi ricevuti */

        if(!strnicmp(buffer,"fine",4))
        {
            Send("Fine collegamento\n\n");
            IsEnd=TRUE;
        }
        else if(!strnicmp(buffer,"host",4))
            Send("Commodore Amiga\n\n");
        else if(!strnicmp(buffer,"baud",4))
            Send("Baud Rate : 2400\n\n");
        else if(!strnicmp(buffer,"data",4))
            Send("Data Bits : 8\n\n");
        else if(!strnicmp(buffer,"stop",4))
            Send("Stop Bits : 1\n\n");
        else if(!strnicmp(buffer,"buffer",6))
            Send("Buffer length : 2 Kbytes\n\n");
        else if(!strnicmp(buffer,"magic",5))
            Send("Magic ? Only Amiga makes it possible !!\n\n");
        else
            Send("Comando sconosciuto\n\n");
    }

    /* il messaggio 'fine' è stato ricevuto */
    /* quindi terminiamo il programma       */

    printf("\nFine del collegamento\n");

    CleanUp();  /* chiusura del dispositivo e deallocazione */
}

/*
 * int OpenSerial(void)
 * 
 * Ottiene l'indirizzo della porta e della struttura dati
 * necessari alla gestione del serial.device.
 * Se queste operazioni hanno avuto successo, viene aperto
 * il serial.device.
 *
 * Input  : nessuno
 *
 * Output : 0 - apertura del dispositivo seriale eseguito con successo
 *          1 - errore durante la richiesta dati/dispositivo
*/
int OpenSerial()
{
    /* creazione della porta da usare con serial.device */

    MyPort=CreatePort("MySerialPort",0);

    if(!MyPort)         /* la porta non è stata creata */
    {
        printf("Errore nella creazione della porta\n");
        return(1);
    }

    /* Creazione ed inizializzazione della struttura dati */

    SerialData = (struct IOExtSer *)CreateExtIO(MyPort,sizeof(struct IOExtSer));

    if(!SerialData)     /* la struttura dati non è stata creata */
    {
        printf("Non posso creare una struttura dati\n");
        return(1);
    }

    /* Apertura del dispositivo seriale */

    if(OpenDevice("serial.device",0,(struct IORequest *)SerialData,0))
    {
        printf("Non posso aprire il dispositivo seriale\n");
        return(1);
    }

    /* Se arriviamo in questo punto, tutto procede bene   */
    /* quindi possiamo impostare la porta seriale secondo */
    /* le nostre esigenze                                 */

    SerialData->IOSer.io_Command=SDCMD_SETPARAMS;       /* Comando di impostazione specifiche */
    SerialData->io_RBufLen=2048L;                       /* 2 Kb di buffer dati */
    SerialData->io_Baud=2400;                           /* Velocita di trasmissione (baudrate) */
    SerialData->io_TermArray.TermArray0=0x0d0a0d0a;     /* Caratteri di break */
    SerialData->io_TermArray.TermArray1=0x0d0a0d0a;     /* Caratteri di break */
    SerialData->io_ReadLen=8;                           /* 8 bit dati in lettura */
    SerialData->io_WriteLen=8;                          /* 8 bit dati in scrittura */
    SerialData->io_StopBits=1;                          /* 1 bit di stop */
    SerialData->io_SerFlags=SERF_EOFMODE|SERF_XDISABLED;

    /* Note sui flags:
     *                  SERF_EOFMODE   : controllo sui caratteri di break (io_TermArray)
     *                  SERF_XDISABLED : Disabilita la modalità XON/XOFF
    */

    DoIO((struct IORequest *)SerialData);   /* Impostazione del dispositivo */

    DevOpened=TRUE;

    return(0);          /* Il dispositivo è ora aperto ed */
                        /* inizializzato correttamente    */
}

/*
 * void Send(char *)
 *
 * Trasmette al dispositivo seriale la stringa di caratteri
 * passata come argomento.
 *
 * Input  : stringa di caratteri da trasmettere
 * Output : nessuno
*/
void Send(string)
char *string;
{
    SerialData->IOSer.io_Command=CMD_WRITE; /* Comando di scrittura su dispositivo   */

    SerialData->IOSer.io_Length=-1;         /* -1 significa di trasmettere tutti i   */
                                            /* caratteri della stringa fino a quando */
                                            /* non si incontra il carattere nullo    */

    SerialData->IOSer.io_Data=(APTR)string; /* Indirizzo della stringa da trasmettere */

    DoIO((struct IORequest *)SerialData);   /* Invio del comando al serial.device */
}

/*
 * void CleanUp(void)
 *
 * Dealloca tutti i dati e le risorse ottenute
 *
 * Input  : nessuno
 * Output : nessuno
*/
void CleanUp()
{
    /* se il serial.device è aperto viene chiuso */
    if(DevOpened)   CloseDevice((struct IORequest *)SerialData);

    /* se è stata allocata una struttura dati viene deallocata */
    if(SerialData)  DeleteExtIO((struct IORequest *)SerialData);

    /* se è stata create una porta viene rilasciata al sistema */
    if(MyPort)      DeletePort(MyPort);
}

