/*
        --- Comunicazione attraverso la porta seriale RS-232 ---
*/

#include "pulldown.h"
#include <bios.h>
#include <stdlib.h>



int porta;
int parametri;

num2word(int num,char *str)
{
        long i;


        strcpy(str,"");
        for (i=32768; i; i=i/2)
        if (num & i) strcat(str,"1");
        else strcat(str,"0");
}

num2byte(int num,char *str)
{
        int i;


        strcpy(str,"");
        for (i=128; i; i=i/2)
        if (num & i) strcat(str,"1");
        else strcat(str,"0");
}

long bit2num(char *caratteri)
{
        int lung,i;
        long p,r,risultato;



        lung=strlen(caratteri); p=0; r=1; i=0; risultato=0;
        i=lung;
        while (i>0)
        {
               p=p+r;
               r=p;
               if (caratteri[i-1]=='1') risultato=risultato+p;
               i--;
        };
        return risultato;
};

predefinito()
{
        union REGS ir;
        union REGS or;
        char *stringabyte;


        porta=0;
        parametri=0xe3;
        ir.x.dx = porta; // Indirizzo della porta seriale COM2
        ir.h.ah = 0; // Inizializzazione della porta seriale
        ir.h.al = parametri; // Seleziona parametri di comunicazione
        int86(0x14,&ir,&or);
};

reimposta()
{
        union REGS ir;
        union REGS or;
        int msg,ritorno,param,i;
        char mem[2000];
        char *port[]={
               "COM1",
               "COM2",
               "COM3",
               "COM4",
               NULL
        };
        char *bps[]={
               "110",
               "150",
               "300",
               "600",
               "1200",
               "2400",
               "4800",
               "9600",
               NULL
        };
        char *parita[]={
               "Nessuna parità",
               "Parità dispari",
               "Parità pari",
               NULL
        };
        char *stop[]={
               "1 bit",
               "2 bit",
               NULL
        };
        char *dati[]={
               "7 bit",
               "8 bit",
               NULL
        };

        box(20,4,60,12,1,1,219,TRUE,15);
        scrivi(26,5,7,1,"Impostazione della porta");
        scrivi(22,7,15,1,"Porta");
        scrivi(22,8,15,1,"Baud rate");
        scrivi(22,9,15,1,"Parità");
        scrivi(22,10,15,1,"Bit di stop");
        scrivi(22,11,15,1,"Lunghezza carattere");

        scrivi(22,7,10,1,"Porta");
        gettext(36,6,60,20,mem);
        msg=finestra(port,36,6, 14,2,9,0,1,2,15,32,&ritorno);
        puttext(36,6,60,20,mem);
        scrivi(22,7,15,1,"Porta");
        porta=msg-1;
        scrivi(44,7,14,1,port[msg-1]);

        scrivi(22,8,10,1,"Baud rate");
        gettext(36,6,60,20,mem);
        msg=finestra(bps,36,6, 14,2,9,0,1,2,15,32,&ritorno);
        puttext(36,6,60,20,mem);
        scrivi(22,8,15,1,"Baud rate");
        param=0;
        for (i=0; i<(msg-1); i++) param=param+32;
        scrivi(44,8,14,1,bps[msg-1]);
 
        scrivi(22,9,10,1,"Parita");
        gettext(36,6,60,20,mem);
        msg=finestra(parita,36,6, 14,2,9,0,1,2,15,32,&ritorno);
        puttext(36,6,60,20,mem);
        scrivi(22,9,15,1,"Parita");
        if (msg==2) param=param+8;
        if (msg==3) param=param+24;
        scrivi(44,9,14,1,parita[msg-1]);

        scrivi(22,10,10,1,"Bit di stop");
        gettext(36,6,60,20,mem);
        msg=finestra(stop,36,6, 14,2,9,0,1,2,15,32,&ritorno);
        puttext(36,6,60,20,mem);
        scrivi(22,10,15,1,"Bit di stop");
        if (msg-1) param=param+4;
        scrivi(44,10,14,1,stop[msg-1]);

        scrivi(22,11,10,1,"Lunghezza carattere");
        gettext(36,6,60,20,mem);
        msg=finestra(dati,36,6, 14,2,9,0,1,2,15,32,&ritorno);
        puttext(36,6,60,20,mem);
        scrivi(22,11,15,1,"Lunghezza carattere");
        if (msg-1) param=param+3;
        else param=param+2;
        scrivi(44,11,14,1,dati[msg-1]);

        parametri=param;
        ir.x.dx = porta; // Indirizzo della porta seriale COMX
        ir.h.ah = 0; // Inizializzazione della porta seriale
        ir.h.al = parametri; // Seleziona parametri di comunicazione
        int86(0x14,&ir,&or);
        box(20,4,60,12,0,0,219,FALSE,-1);
};

int scrivi_dati(char dato,int porta)
{
        union REGS ir;
        union REGS or;
        union bits valori;
        long val;
        char str1[10];


        ir.x.dx = porta; // Indirizzo della porta seriale COMX
        ir.h.ah = 1; // Scrittura sulla porta seriale
        ir.h.al = dato; // Carattere da trasmettere
        int86(0x14,&ir,&or);
        val=or.h.ah; // Stato della trasmissione
        num2byte(val,str1);
        val=or.h.al; // Stato del modem
        num2byte(val,str1);

        if (str1[0]=='1')
        {
               box(20,4,60,6,2,2,219,TRUE,0);
               scrivi(25,5,1,2,"Errore durante la trasmissione !");
               getch();
               return 0;
        } else return 1;
};

char leggi_dati(int porta)
{
        union REGS ir;
        union REGS or;
        union bits valori;
        char dato,str1[10];
        int val;


        ir.x.dx = porta; // Indirizzo della porta seriale COMX
        ir.h.ah = 2; // Ricezione dalla porta seriale
        int86(0x14,&ir,&or);
        val=or.h.ah; // Stato della trasmissione
        num2byte(val,str1);

        dato=or.h.al; // Carattere ricevuto
        return dato;
};

invia_ricevi()
{
        int fine,x,y,c,x1,y1,oktx;
        long val;
        char dato,str1[5],datorx;
        union REGS ir,or;


        box(1,2,80,11,4,4,219,TRUE,14);
        box(1,12,80,22,4,4,219,TRUE,14);
        scrivi(32,2,11,4," Trasmissione dati ");
        scrivi(33,12,11,4," Ricezione dati ");
        fine=FALSE; x=0; y=0; x1=0; y1=1; textcolor(15);
        while (!fine)
        {
               ir.x.dx = porta; // Seleziona la COMX
               ir.h.ah = 3; // Preleva stato della porta seriale
               int86(0x14,&ir,&or);
               val=or.h.al; // Stato del Modem
               num2byte(val,str1);
               val=or.h.ah; // Stato della linea
               num2byte(val,str1);

               dato=getch();
               gotoxy(2+x+x1,2+y+y1);
               putch(dato);
               oktx=scrivi_dati(dato,porta);

               datorx=leggi_dati(porta);
               gotoxy(2+x+x1,12+y+y1);
               putch(datorx);

               c++; x1++;
               if (!(x1%78)) {x1=0; y1++;};
               if ((!(x1%78)) && (!(y1%9))) { x1=0; y1=1; };
               if (dato==27) fine=TRUE;
        };
        box(1,2,80,22,0,0,219,FALSE,-1);
}

stato()
{
        union REGS ir;
        union REGS or;
        union bits valori;
        int msg,ritorno,val;
        char mem[2000],str1[20];
        char *porta[]={
               "COM1",
               "COM2",
               "COM3",
               "COM4",
               NULL
        };

        box(20,4,60,16,1,1,219,TRUE,15);
        scrivi(28,5,7,1,"Stato della linea seriale");
        scrivi(22,7,15,1 ,"Porta");
        scrivi(22,8,15,1 ,"Errore per fuori tempo");
        scrivi(22,9,15,1 ,"TSR vuoto");
        scrivi(22,10,15,1,"HSR vuoto");
        scrivi(22,11,15,1,"Rilevata interruzione di break");
        scrivi(22,12,15,1,"Errore di riferimento");
        scrivi(22,13,15,1,"Errore di parit…");
        scrivi(22,14,15,1,"Errore di sovrapposizione");
        scrivi(22,15,15,1,"Dati disponibili");
        scrivi(22,7,10,1,"Porta");
        gettext(36,6,60,20,mem);
        msg=finestra(porta,36,6, 14,2,9,0,1,2,15,32,&ritorno);
        puttext(36,6,60,20,mem);
        scrivi(22,7,15,1,"Porta");
        scrivi(54,7,14,1,porta[msg-1]);

        ir.x.dx = msg-1; // Seleziona la COMX
        ir.h.ah = 3; // Preleva stato della porta seriale
        int86(0x14,&ir,&or);
        val=or.h.ah;
        num2byte(val,str1);
        if (str1[0]=='1') scrivi(54,8,14,1,"X");
               else scrivi(54,8,14,1,".");
        if (str1[1]=='1') scrivi(54,9,14,1,"X");
               else scrivi(54,9,14,1,".");
        if (str1[2]=='1') scrivi(54,10,14,1,"X");
               else scrivi(54,10,14,1,".");
        if (str1[3]=='1') scrivi(54,11,14,1,"X");
               else scrivi(54,11,14,1,".");
        if (str1[4]=='1') scrivi(54,12,14,1,"X");
               else scrivi(54,12,14,1,".");
        if (str1[5]=='1') scrivi(54,13,14,1,"X");
               else scrivi(54,13,14,1,".");
        if (str1[6]=='1') scrivi(54,14,14,1,"X");
               else scrivi(54,14,14,1,".");
        if (str1[7]=='1') scrivi(54,15,14,1,"X");
               else scrivi(54,15,14,1,".");
        getch();
        box(13,4,67,16,1,1,219,TRUE,15);
        scrivi(33,5,7,1,"Stato del Modem");
        scrivi(15,7,15,1 ,"Porta");
        scrivi(15,8,15,1 ,"Rilevato segnale di ricezione sulla linea");
        scrivi(15,9,15,1 ,"Indicatore di chiamata");
        scrivi(15,10,15,1,"Dati disponibili (DSR)");
        scrivi(15,11,15,1,"Abilitazione a trasmettere (CTS)");
        scrivi(15,12,15,1,"Rilevato segnale di ricezione sulla linea delta");
        scrivi(15,13,15,1,"Rilevatore di chiamata a fronte di salita");
        scrivi(15,14,15,1,"Dati disponibili delta (DDSR)");
        scrivi(15,15,15,1,"Abilitazione a trasmettere delta (DCTS)");
        scrivi(62,7,14,1,porta[msg-1]);

        ir.x.dx = msg-1; // Seleziona la COMX
        ir.h.ah = 3; // Preleva stato della porta seriale
        int86(0x14,&ir,&or);
        val=or.h.al;
        num2byte(val,str1);
        if (str1[0]=='1') scrivi(63,8,14,1,"X");
               else scrivi(63,8,14,1,".");
        if (str1[1]=='1') scrivi(63,9,14,1,"X");
               else scrivi(63,9,14,1,".");
        if (str1[2]=='1') scrivi(63,10,14,1,"X");
               else scrivi(63,10,14,1,".");
        if (str1[3]=='1') scrivi(63,11,14,1,"X");
               else scrivi(63,11,14,1,".");
        if (str1[4]=='1') scrivi(63,12,14,1,"X");
               else scrivi(63,12,14,1,".");
        if (str1[5]=='1') scrivi(63,13,14,1,"X");
               else scrivi(63,13,14,1,".");
        if (str1[6]=='1') scrivi(63,14,14,1,"X");
               else scrivi(63,14,14,1,".");
        if (str1[7]=='1') scrivi(63,15,14,1,"X");
               else scrivi(63,15,14,1,".");
        getch();
        box(13,4,67,16,0,0,219,FALSE,-1);
};

visparam()
{
        int x,y,val;
        char str1[20],str2[8];


        x=1; y=3;
        box(45+x,3+y,70+x,11+y,2,2,219,TRUE,15);
        scrivi(49+x,3+y,8,2," Parametri RS-232 ");
        scrivi(47+x,5+y,14,2,"Porta");
        scrivi(47+x,6+y,14,2,"Baud Rate");
        scrivi(47+x,7+y,14,2,"Parit…");
        scrivi(47+x,8+y,14,2,"Bit Stop");
        scrivi(47+x,9+y,14,2,"Bit dati");

        if (porta==0) { scrivi(60+x,5+y,10,2,"COM1"); }
        if (porta==1) { scrivi(60+x,5+y,10,2,"COM2"); }
        if (porta==2) { scrivi(60+x,5+y,10,2,"COM3"); }
        if (porta==3) { scrivi(60+x,5+y,10,2,"COM4"); }
        num2byte(parametri,str1);
        str2[0]=str1[0]; str2[1]=str1[1]; str2[2]=str1[2]; str2[3]='\0';
        val=bit2num(str2);
        switch (val)
        {
               case 0: { scrivi(60+x,6+y,10,2,"110"); break; };
               case 1: { scrivi(60+x,6+y,10,2,"150"); break; };
               case 2: { scrivi(60+x,6+y,10,2,"300"); break; };
               case 3: { scrivi(60+x,6+y,10,2,"600"); break; };
               case 4: { scrivi(60+x,6+y,10,2,"1200");break; };
               case 5: { scrivi(60+x,6+y,10,2,"2400");break; };
               case 6: { scrivi(60+x,6+y,10,2,"4800");break; };
               case 7: { scrivi(60+x,6+y,10,2,"9600");break; };
        };
        str2[0]=str1[3]; str2[1]=str1[4]; str2[2]='\0';
        val=bit2num(str2);
        switch (val)
        {
               case 0: { scrivi(60+x,7+y,10,2,"Nessuna"); break; };
               case 1: { scrivi(60+x,7+y,10,2,"Dispari"); break; };
               case 2: { scrivi(60+x,7+y,10,2,"Nessuna"); break; };
               case 3: { scrivi(60+x,7+y,10,2,"Pari"); break; };
        };
        str2[0]=str1[5]; str2[1]='\0';
        val=bit2num(str2);
        switch (val)
        {
               case 0: { scrivi(60+x,8+y,10,2,"1 Bit"); break; };
               case 1: { scrivi(60+x,8+y,10,2,"2 Bit"); break; };
        };
        str2[0]=str1[6]; str2[1]=str1[7]; str2[2]='\0';
        val=bit2num(str2);
        switch (val)
        {
               case 2: { scrivi(60+x,9+y,10,2,"7 Bit"); break; };
               case 3: { scrivi(60+x,9+y,10,2,"8 Bit"); break; };
        };
};

void main()
{
        clrscr();
        char *opz1[]={
               "RS-232",
               "Fine",
               NULL
        };
        char *opz2[]={
               "Reimposta",
               "Stato",
               "Comunica",
               NULL
        };
        char *opz3[]={
               "NO",
               "SI",
               NULL
        };
        int opzione,ritorno,msg,msg2,fine,ok;
        char dato,*strbit;


        textbackground(0); cursore(0);
        clrscr(); fine=FALSE;
        predefinito();
        while (!fine)
        {
               box(1,24,80,24,1,1,32,FALSE,-1);
               scrivi(2,24,14,1,"Comunicazione seriale");
               visparam();
               opzione=menu(opz1,15,1,14,2,1);
               switch (opzione)
               {
               case 1 : {
                             msg=finestra(opz2,2,2, 15,1,14,4,1,1,15,32,&ritorno);
                             if (!ritorno)
                             {
                                    box(2,2,30,12,0,0,32,FALSE,-1);
                                    if (msg==1)
                                    { // Inizializzazione
                                           reimposta();
                                    };
                                    if (msg==2)
                                    { // Stato
                                           stato();
                                    };
                                    if (msg==3)
                                    { // Invia - Ricevi Tx-Rx
                                           invia_ricevi();
                                    };
                             } else { box(2,2,20,6,0,0,32,-1,FALSE);}
                             break;
                             };
               case 2 : {
                             msg=finestra(opz3,13,2, 15,1,14,4,1,1,15,32,&ritorno);
                             box(13,2,20,6,0,0,32,-1,FALSE);
                             if (!ritorno)
                             {
                             if (msg==2)
                             {
                                    fine=TRUE;
                             }
                             }
                             break;
                             };
                             };
        }
        textbackground(0); textcolor(7);
        cursore(1);
        clrscr();
}