// tab space = 4

/***********************************************************************/

/*                                                                     */

/*  FILE        :main.c                                                */

/*  DATE        :July 6, 2004                                       */

/*  DESCRIPTION :Main Program                                          */

/*                                                                     */

/***********************************************************************/

                  

#include "skp_bsp.h" // include SKP board support package

#include "skp_lcd.h" // include SKP LCD support package

#include <stdio.h>



#define  TIME_CONFIG 0x40  

/*  01000000 value to load into timer mode register

                    ||||||||_  TMOD0,TMOD1: TIMER MODE SELECTED

                    ||||||____ MR0:         NO PULSE OUTPUT   

                    |||||_____ MR1,MR2:     GATE FUNCTION NOT SELECTED

                    |||_______ MR3:         SET TO 0 IN TIMER MODE     

                    ||________ TCK0,TCK1:   F DIVIDED BY 8 SELECTED */


#define FREQ_RESOLUTION   (f1_CLK_SPEED/8)  

#define TIME_RELOAD (unsigned int)(((FREQ_RESOLUTION)*5e-3) - 1) //5ms

#define BUTTON_TICK   500 // 500ms

#define DATA_TIMEOUT 1000 // 1 Seconds 

        

#define  CNTR_IPL 0x03   // TA2  priority interrupt level

#define INT2_IPL 0x02 //INT0 priority interrupt level


#define MAX_EVENTS 128 //


#define MENUS 9

#define MENU_Spy 8

#define MENU_Voltage 7

#define MENU_Detect 6

#define MENU_Analyse 5

#define MENU_Guess 4

#define MENU_Freq 1

#define MENU_Period 2

#define MENU_Events 3

#define MENU_Title 0


#define MODE_DETECT 0

#define MODE_ACQUIRE 1

#define MODE_ANALYSE 2

#define MODE_SPY 3


#define HISTROGRAM_MAX 12

#define ROLLOVER FALSE


#define NONE 0

#define ODD 1

#define EVEN 2


/* Defins for HW connections */


#define AN_F2 ad3 //p10_3 // Analog input for Female DB9 pin 2

#define AN_F3 ad2 //p10_2 // Analog input for Female DB9 pin 3

#define AN_M2 ad5 //p10_5 // Analog input for Male DB9 pin 2

#define AN_M3 ad4 //p10_4 // Analog input for Male DB9 pin 3

#define RXD_F p8_4 // RXD from Female DB9

#define RXD_M p8_3 // RXD from Male DB9

#define ENFA p7_3 // Enable Female tranciever, Normal

#define ENFB p7_5 // Enable Female tranciever, X over 

#define ENMA p7_6 // Enable Male tranciever, Normal

#define ENMB p7_7 // Enable Male tranciever, X over

#define DDR_RXD_F pd8_4 // RXD from Female DB9

#define DDR_RXD_M pd8_3 // RXD from Male DB9

#define DDR_ENFA pd7_3 // Enable Female tranciever, Normal

#define DDR_ENFB pd7_5 // Enable Female tranciever, X over 

#define DDR_ENMA pd7_6 // Enable Male tranciever, Normal

#define DDR_ENMB pd7_7 // Enable Male tranciever, X over


#define VOLTAGE_232 613 //613 = ((-5V/-10 + 2.5V)/ 5V )* 1023


unsigned int this_edge;

unsigned int last_edge;

unsigned int time_cnt;

unsigned int dtime_cnt;

unsigned int ovf_count;       


unsigned char event_cnt; // Global event counter points to current event

unsigned char event_total;

 long event[MAX_EVENTS];  // storage for transition times

unsigned char event_lvl[(MAX_EVENTS/8)+1]; //storage for bit levels

unsigned int event_bits[MAX_EVENTS]; // storage for transition times (in bits)


unsigned char display[2][9]; // variable to hold/construct display string

unsigned char menu;

unsigned char Update_LCD;

unsigned char waiting;

unsigned char reset_on_next;

unsigned char Mode;

unsigned char integer_fmt;


unsigned char histogram[HISTROGRAM_MAX];

unsigned int  VoltageF;

unsigned int  VoltageM;


char gParity;

char gDataBits;

char gStopBits=1;


char U0_in; // declare UART0 recieve variable

char U2_in; // declare UART2 recieve variable


char cables=0;


#define BAUDRATES 17

const unsigned long BAUD_TABLE[BAUDRATES] = 

{110,300,600,1200,2400,4800,9600,

14400,19200,28800,38400,57600,76800,

115200,230400,256000};



#pragma INTERRUPT ta2_irq 

#pragma INTERRUPT int0_irq 

#pragma INTERRUPT int1_irq

#pragma INTERRUPT int2_irq

#pragma INTERRUPT U0rec_ISR

#pragma INTERRUPT U2rec_ISR



/* Prototype declarations */

void mcu_init(void); // MCU initialization

void main(void);

void LCD_Update(void);

void buttons(void);


void tmr_init(void);

void int_init(char channel);

void ta2_irq (void);

void int2_irq(void);

void U0rec_ISR (void);

void U2rec_ISR (void);


unsigned long int_period(void);

unsigned long int_baud(void);

float flt_period(void);

float flt_baud(void);

char guess_baud(void);

void bit_analysis(void);

void configurePins(void);

void StopMonitoring(void);

void StartMonitoring(void);

void text_write ( _far char * msg_string);



/******************************************************************************

Name       : main

Parameters : none

Returns    : nothing

Description: Main template

******************************************************************************/

void main(void)

{

integer_fmt = TRUE;


/* Initialize MCU

*/

mcu_init();

InitDisplay();

tmr_init();

DisplayString(LCD_LINE1 ,RENESAS_LOGO);

DisplayString(LCD_LINE2, __TIME__);


/* Detect RS232 Voltages and setup Pins

*/

Mode = MODE_DETECT;

configurePins();

menu=MENU_Detect;


time_cnt = 0;  

dtime_cnt =0;

ovf_count = 0;

event_cnt=0;

event_total=0;

reset_on_next=TRUE;


ENABLE_LEDS; /* LED initialization for this demo - macro defined in skp_bsp.h */

ENABLE_SWITCHES;


while(1){

buttons();

if (Update_LCD){

Update_LCD = FALSE;

LCD_Update();

}

};

}


/*****************************************************************************

Name:     configurePins      

Parameters: none                     

Returns:  none      

Description: Checks the analog levels of rs232 pins to decide which are

TXD and RXD pins on each connector.

**************************************************************************** */ 

void configurePins(void)

{

int f2=512;

int f3=512;

int m2=512;

int m3=512;

cables =0;


while (cables==0){


// disable trancievers

DDR_ENFA = 1;

DDR_ENFB = 1;

DDR_ENMA = 1;

DDR_ENMB = 1;

ENFA = FALSE;

ENFB = FALSE;

ENMA = FALSE;

ENMB = FALSE;


//setup ADC

adcon0 = 0x90;

      /*

        10010000;  ** Repeat sweep mode 0, soft trigger, fAD/2

    ||||||||______Analog input select bit 0

    |||||||_______Analog input select bit 1

    ||||||________Analog input select bit 2

    |||||_________A/D operation mode select bit 0

    ||||__________A/D operation mode select bit 1

    |||___________Trigger select bit

    ||____________A/D conversion start flag

    |_____________Frequency select bit 0 */


adcon1 = 0x3A;

      /*

      00111010; ** Scan AN0-AN%, 10-bit mode, fAD/2, Vref connected

    ||||||||______A/D sweep pin select bit 0

    |||||||_______A/D sweep pin select bit 1

    ||||||________A/D operation mode select bit 1

    |||||_________8/10 bit mode select bit

    ||||__________Frequency select bit 1

    |||___________Vref connect bit

    ||____________External op-amp connection mode bit 0

    |_____________External op-amp connection mode bit 1 */   


adcon2 = 0x01;

      /*

      00000001; ** Sample and hold enabled, fAD/2

    ||||||||______AD conversion method select bit

            |||||||_______AD input group select bit 0

      ||||||________AD input group select bit 1

      |||||_________Reserved

      ||||__________Frequency select bit 2

      |||___________Reserved

      ||____________Reserved

      |_____________Reserved */


    adst = 1; // Start a conversion here


    while (adst); // wait for conversions to be done.


 

f2= AN_F2 & 0x03ff; // Mask off the upper 6 bits of the 

// variable leaving only the result

// in the variable itself


f3= AN_F3 & 0x03ff; // Mask off the upper 6 bits of the 

// variable leaving only the result

// in the variable itself


m2= AN_M2 & 0x03ff; // Mask off the upper 6 bits of the 

// variable leaving only the result

// in the variable itself


m3= AN_M3 & 0x03ff; // Mask off the upper 6 bits of the 

// variable leaving only the result

// in the variable itself

// enable correct trancievers by looking for negative voltages

if (f2>VOLTAGE_232){ // 573 = ((-3V/-10 + 2.5V)/ 5V )* 1023 

DisplayString(LCD_LINE2 ,"DB9F    ");

ENFA = TRUE;

ENFB = FALSE;

VoltageF = (f2-512) ;

}else if  (f3>VOLTAGE_232){

DisplayString(LCD_LINE2 ,"DB9F Xvr");

ENFA = FALSE;

ENFB = TRUE;

VoltageF = (f3-512);

}else{ // no DB9F Detected

//DisplayString(LCD_LINE2 ,"No DB9F ");

}


if (m2>VOLTAGE_232){

DisplayString(LCD_LINE1, "DB9M    ");

ENMA = FALSE;

ENMB = TRUE;

VoltageM = (m2-512) ;

}else if (m3>VOLTAGE_232){

DisplayString(LCD_LINE1, "DB9M Xvr");

ENMA = TRUE;

ENMB = FALSE;

VoltageM = (m3-512) ;

}else{ // no DB9M Detected

//DisplayString(LCD_LINE1, "No DB9M ");

}


// check number of cables and setup interrupts accordingly.

cables = (char) (ENFA + ENFB + ENMA + ENMB);

switch (cables){

case 0:

DisplayString(LCD_LINE1 ,"No cable");

DisplayString(LCD_LINE2, "detected");

int_init(0);

break;

case 1:

if (ENFA+ENFB){ // DB9F

int_init(2);

}else{ // DB9M

int_init(1);

}

break;

case 2:

int_init(2); // DB9F by default

break;

}

}

// while(!S2);


}


/*****************************************************************************

Name:     buttons     

Parameters: none                     

Returns:  none      

Description: Polls buttons and adjust apropriate gloabl variables

**************************************************************************** */ 

void buttons(void)

{

if (!waiting){

if (!S3){ // next

menu ++;

Update_LCD=TRUE;

waiting=TRUE;

}

// if (!S1){ // prev

// menu --;

// Update_LCD=TRUE;

// waiting=TRUE;

// }

if (!S2){ //enter

Update_LCD =TRUE;

Mode != Mode;

switch (menu % (MENUS)){

case MENU_Freq:

case MENU_Voltage:

case MENU_Period:

integer_fmt ^= TRUE;

waiting=TRUE;

break;

case MENU_Events:

event_cnt=0;

event_total =0;

//event[0]=-1;

waiting=TRUE;

break;

case MENU_Spy:

waiting=TRUE;

if (Mode == MODE_SPY){

Mode = MODE_ACQUIRE;

StopMonitoring();

}else{

Mode = MODE_SPY;

StartMonitoring();

}

//case MENU_Guess: //switch to analyse mode

//case MENU_Analyse:

}

}

}

}


/*****************************************************************************

Name:     LCD_Update     

Parameters: integer_fmt, show numbers as floats or integers                     

Returns:  none      

Description: display current data on LCD

**************************************************************************** */ 

void LCD_Update(void)

{

float error=0;

float temp=0;

float temp2=0;


LCD_write(CTRL_WR,LCD_CLEAR);


switch (menu % (MENUS)){

case MENU_Freq:

LCD_write(CTRL_WR,LCD_CLEAR);

if (integer_fmt){

sprintf(display[0],"%8u",int_baud());

}

else{

sprintf(display[0],"%8.1f",flt_baud());

}

DisplayString(LCD_LINE1 ,"Baud bps");

DisplayString(LCD_LINE2 ,display[0]);

break;

case MENU_Period:

temp=flt_period();

if (integer_fmt){

if (temp>1000)

sprintf(display[0],"%6umS",(temp/=1000));

else

sprintf(display[0],"%6uuS",int_period());

}

else{

if (temp>1000)

sprintf(display[0],"%6.1fms",(temp/=1000));

else

sprintf(display[0],"%6.1fus",flt_period());

}

DisplayString(LCD_LINE1 ,"Period ");

DisplayString(LCD_LINE2 ,display[0]);

break;

case MENU_Events:

LCD_write(CTRL_WR,LCD_CLEAR);

sprintf(display[0],"%d/%d",event_cnt,event_total);

DisplayString(LCD_LINE1 ,"Events");

DisplayString(LCD_LINE2 ,display[0]);

break;

case MENU_Title:

DisplayString(LCD_LINE1 ," Quick  ");

DisplayString(LCD_LINE2 ,"Coms 0.1");

break;

case MENU_Guess:

LCD_write(CTRL_WR,LCD_CLEAR);

error = (1- ( (float) flt_baud() / (float) BAUD_TABLE[guess_baud()]) )*100;

if (error>0)

error = 100-error;

else

error +=100; 

sprintf(display[0],"%8.0f",(float) BAUD_TABLE[guess_baud()]);

sprintf(display[1],"%7.2f%%",error);

DisplayString(LCD_LINE1 ,display[1]);

DisplayString(LCD_LINE2 ,display[0]);

break;

case MENU_Analyse:

Mode = MODE_ANALYSE;

bit_analysis();

break;

case MENU_Detect:

Mode = MODE_DETECT;

configurePins();

Mode = MODE_ACQUIRE;

break;

case MENU_Voltage:

temp = (float) VoltageF /20.0;

temp2= (float) VoltageM /20.0;


switch(cables){

case 0:

menu++; // skip to next menu

break;


case 1:

sprintf(display[0],"Voltage");

if (integer_fmt){

if (ENFA+ENFB){

sprintf(display[1],"%dV",VoltageF/20);

}else{

sprintf(display[1],"%dV",VoltageM/20);

}

}else{

if (ENFA+ENFB){

sprintf(display[1],"%2.2fV",temp);

}else{

sprintf(display[1],"%2.2fV",temp2);

}

}

break;


case 2:

if (integer_fmt){

sprintf(display[0],"M: %dV",VoltageM/20);

sprintf(display[1],"F: %dV",VoltageF/20);

}else{

sprintf(display[0],"M: %2.2fV",temp2);

sprintf(display[1],"F: %2.2fV",temp);

}

}


DisplayString(LCD_LINE1 ,display[0]);

DisplayString(LCD_LINE2 ,display[1]);

break;


case MENU_Spy:

DisplayString(LCD_LINE1 ,"Monitor");

if (Mode == MODE_SPY){

DisplayString(LCD_LINE2,"  Stop  ");

}else{

DisplayString(LCD_LINE2,"  Start  ");

}

break;

}



}



void int0_irq(void)

{

}


void int1_irq(void)

{

// capture timer reading 

this_edge = ta2;

if (Mode == MODE_ACQUIRE){

// clear all data after a timeout

if (reset_on_next){

event_cnt=0;

event_total=0;

RED_LED = LED_OFF;

reset_on_next = FALSE;

}

// store timer value and overflows

if (!ovf_count){

event[event_cnt] = last_edge - this_edge; 

}else if(ovf_count==1){

event[event_cnt] = last_edge + (TIME_RELOAD - this_edge);

}else{

event[event_cnt] = last_edge + (TIME_RELOAD - this_edge) + ((ovf_count-1) * TIME_RELOAD);

}

// record the level.

if (p8_3) 

event_lvl[event_cnt/8] |= (1<<(char)(event_cnt%8));//set this bit

else

event_lvl[event_cnt/8] &= ~(1<<(char)(event_cnt%8));//clear this bit


event_cnt++;


// reset timmers

last_edge = this_edge;

ovf_count=0;

time_cnt=0;

dtime_cnt=0;


// let user know event has been captured

GRN_LED = LED_ON;


if (ROLLOVER){

if (event_cnt==MAX_EVENTS){ // reset pointer to start of buffer

event_cnt=0;

}

}else if (event_cnt==MAX_EVENTS){

Mode=MODE_ANALYSE;

}

if (event_total<MAX_EVENTS){ // move pointer to fil the buffer

event_total++;

}

}

}


void int2_irq(void)

{

// capture timer reading 

this_edge = ta2;

if (Mode == MODE_ACQUIRE){

// clear all data after a timeout

if (reset_on_next){

event_cnt=0;

event_total=0;

RED_LED = LED_OFF;

reset_on_next = FALSE;

}

// store timer value and overflows

if (!ovf_count){

event[event_cnt] = last_edge - this_edge; 

}else if(ovf_count==1){

event[event_cnt] = last_edge + (TIME_RELOAD - this_edge);

}else{

event[event_cnt] = last_edge + (TIME_RELOAD - this_edge) + ((ovf_count-1) * TIME_RELOAD);

}

// record the level.

if (p8_4) 

event_lvl[event_cnt/8] |= (1<<(char)(event_cnt%8));//set this bit

else

event_lvl[event_cnt/8] &= ~(1<<(char)(event_cnt%8));//clear this bit


event_cnt++;


// reset timmers

last_edge = this_edge;

ovf_count=0;

time_cnt=0;

dtime_cnt=0;


// let user know event has been captured

GRN_LED = LED_ON;


if (ROLLOVER){

if (event_cnt==MAX_EVENTS){ // reset pointer to start of buffer

event_cnt=0;

}

}else if (event_cnt==MAX_EVENTS){

Mode=MODE_ANALYSE;

}

if (event_total<MAX_EVENTS){ // move pointer to fil the buffer

event_total++;

}

}


}


/*****************************************************************************

Name:     ta2_irq()       

Parameters: none                     

Returns:  nothing      

Description:Timer A2 Interrupt Service Routine. Interrupts every 5 msec,

            toggles LED every second, and increments global'count'   

**************************************************************************** */

void ta2_irq (void)

{

if (Mode == MODE_ACQUIRE){

ovf_count++;

}


  if ((time_cnt += 5) > (BUTTON_TICK)){   

  YLW_LED ^= 1;                 // toggle LED ON-OFF-ON

if (GRN_LED == LED_ON){

GRN_LED = LED_OFF; // turn off green light

Update_LCD=TRUE;

}

if ( (menu % (MENUS))== MENU_Detect){

if (cables>0)

configurePins();

Update_LCD=TRUE;

}

    time_cnt = 0;

waiting = FALSE; //clear button timer

  }



if((dtime_cnt+=5)> (DATA_TIMEOUT)){

RED_LED =1;

reset_on_next = TRUE;

/* if (Mode == MODE_ANALYSE){

Mode = MODE_ACQUIRE;

}else if((Mode == MODE_ACQUIRE )&&(event_total>5)){//wehave data?

Mode = MODE_ANALYSE;

bit_analysis();

}*/

}

}


void alert(void){

GRN_LED = LED_ON;

RED_LED = LED_ON;

YLW_LED = LED_ON;

}


/*****************************************************************************

Name:  tmr_init()   

Parameters: none                   

Returns:  nothing      

Description: Setup timer A2 setup for 5msec interrupts. BCLK is set to f1

(divide by 1) in the ncrt0 startup file.    

**************************************************************************** */

void tmr_init(){


ta2mr = TIME_CONFIG;

ta2 =  (unsigned int)TIME_RELOAD ;   

/* The recommended procedure for writing an Interrupt Priority Level is shown

   below (see M16C datasheets under 'Interrupts' for details). */


   DISABLE_IRQ // disable irqs before setting irq registers - macro defined in skp_bsp.h

   ta2ic = CNTR_IPL;

    ENABLE_IRQ // enable interrupts macro defined in skp_bsp.h


ta2s = 1; // start timer

}



/*****************************************************************************

Name:     int2_init     

Parameters: inturrup to use, 1,2 or 0 for none.                     

Returns:  none     

Description: Initialize the INT2 interrupt

**************************************************************************** */ 

void int_init(char channel)

{

ifsr2=1; // trigger INT2 on rising and falling edges;

ifsr1=1;  // trigger INT1 on rising and falling edges;

DISABLE_IRQ // disable irqs before setting irq registers - macro defined in skp_bsp.h

switch (channel){

case 1:

int1ic= INT2_IPL;

int2ic = 0;

break;

case 2:

int1ic = 0;

int2ic= INT2_IPL;

break;

case 0:

int2ic = 0;

int1ic = 0;

}

ENABLE_IRQ // enable interrupts macro defined in skp_bsp.h


}



/*****************************************************************************

Name:     min_event_time()

Parameters: none                     

Returns:  Unsigned Long    

Description: Calculates the smallest time between events

**************************************************************************** */ 

unsigned long min_event_time(void)

{

unsigned long period;

unsigned long temp;

char i;


period =  event[0]; 

for (i=0;i<event_total;i++){

temp = event[i]; // ta2 is a down counter

if (temp<period)

period=temp;

}

return period;

}



/*****************************************************************************

Name:     int_baud()       

Parameters: none                     

Returns:  unsigned integer containing largest baud rate from data      

Description: calculates the baudrate of the shortest bit

**************************************************************************** */ 

unsigned long int_baud(void){

unsigned long period;


if (event_total<1){

return 0;

}


period = min_event_time();


if (period>0){

return (unsigned long) ((unsigned long) FREQ_RESOLUTION / period) ;

}

else{

return 0;

}


}


/*****************************************************************************

Name:     flt_baud()       

Parameters: none                     

Returns:  float containing largest baud rate from data      

Description: calculates the baudrate of the shortest bit

**************************************************************************** */ 

float flt_baud(void){

unsigned long period;


if (event_total<1){

return 0;

}


period = min_event_time();

if (period>0){

return (float) FREQ_RESOLUTION / (float) period ;

}

else{

return 0;

}


}


/*****************************************************************************

Name:     int_period()       

Parameters: none                     

Returns:  Pulse width in uS     

Description: calculates the minumum period between any two events

**************************************************************************** */ 

unsigned long int_period(void){

unsigned long long out;

unsigned long long period;


if (event_total<1){

return 0;

}

period = min_event_time();

period *= 1000000; // scale to uS

out =  (period  / FREQ_RESOLUTION );

return (unsigned long)out ; // return period

}


/*****************************************************************************

Name:     flt_period()       

Parameters: none                     

Returns:  Pulse width in uS     

Description: calculates the minumum period between any two events

**************************************************************************** */ 

float flt_period(void){

float out;

if (event_total<1){

return 0;

}

out = min_event_time();

out *= 1000000; 

out /= FREQ_RESOLUTION ;

return out ; // return period

}



/*****************************************************************************

Name:     guess_baud     

Parameters: none                     

Returns:  char index to B      

Description:

**************************************************************************** */ 

char guess_baud(void){

char guess,best=0;

unsigned long actual;

float diff,last;


if (BAUDRATES<1){

return 0;

}


actual = int_baud();


if (actual > BAUD_TABLE[0]){

last = (actual - BAUD_TABLE[0]);

}else{

last = (BAUD_TABLE[0] - actual);

}


for (guess=1;guess<BAUDRATES;guess++){

if (actual > BAUD_TABLE[guess]){

diff = (actual - BAUD_TABLE[guess]);

}else{

diff = (BAUD_TABLE[guess] - actual);

}


if (diff<last){

last = diff;

best = guess;

}

}

return best;

}



/*****************************************************************************

Name:     bit_analysis     

Parameters: none                     

Returns:  none     

Description: analyses the event memory to estimate encodeing scheme.

**************************************************************************** */ 

void bit_analysis(void)

{

float period ;

float calc;

float error;

unsigned char i,j,k;

unsigned char score[13],bitval;

unsigned char word[13],wordlength;

unsigned int bitLength, bitsReceived,bitsTotal,wordsTotal,wordsPossible;

unsigned char parityBit,parity, even,odd; // counters for parity scoring


// convert events to bit time (rounding up to nearest period)

period = FREQ_RESOLUTION/BAUD_TABLE[guess_baud()];

for (i=0;i<event_total;i++){

calc = ((float) event[i]+(period/2))/period; 

if (calc > 12 )

calc =1; //filter large pauses

event_bits[i]=calc;

}


// produce histogram for statistical analysis

for(i=0;i<HISTROGRAM_MAX;i++)

histogram[i]=0;


for (i=0;i<event_total;i++){

if (event_bits[i] <HISTROGRAM_MAX)

histogram[event_bits[i]]++;

else

histogram[0]++;

}

bitsTotal=0;

for(i=0;i<HISTROGRAM_MAX;i++)

bitsTotal+=(histogram[i]*i);



//check start stop combinations 1 stop bit

for (bitLength=7;bitLength<13;bitLength++){

bitsReceived = 0;

score[bitLength]=0;


for(i=1;i<event_total;i++){

bitsReceived += event_bits[i];


if (bitsReceived == (bitLength)) {//this is a single stop bit

if (!(event_lvl[i/8] & (1<<i%8))) {// stop  bit is set

score[bitLength]++; // add one to the score

bitsReceived=0;

}else{// we've got exact bits but wrong level?? do we go forward or back??

bitsReceived=0;

i++;// try starting from next bit

//i-=2;// try starting next word from previous bit.

}

}


if (bitsReceived > (bitLength)) {// overran a stop bit

// this should find next/last 0 bit 

if ((event_lvl[i/8] & (1<<i%8)))

i++;// try starting next word from previous bit.

bitsReceived=0;

// break;

}

}

}

// analyse best score/ total bits recieved.

// find best bit rate

j=6;

score[j]=0;

for (i=7;i<13;i++){

if (score[i]>score[j]){

j=i;

}

}

LCD_write(CTRL_WR,LCD_CLEAR);


wordsPossible=(bitsTotal/j);

wordsTotal=score[j];

wordlength=j;

//error = (wordsTotal*100)/wordsPossible;

if (j>6){//found a winner

sprintf(display[0],"%d words",wordsTotal);

sprintf(display[1],"%d bit",j);


DisplayString(LCD_LINE1 ,display[0]);

DisplayString(LCD_LINE2 ,display[1]);

//

// analyse Parity

//

parityBit=wordlength-2;

bitsReceived=0;

parity=0;

even=0;

odd=0;


for(i=1;i<event_total;i++){

if (event_bits[i]>12)

event_bits[i]=1; // blast long pauses

bitval = ((event_lvl[(i-1)/8] & (1<<(i-1)%8))!=0);// get pulse value


for (k=0; k<event_bits[i]; k++){ // expand out into individual bits

word[k+bitsReceived]= bitval;

parity += word[k+bitsReceived]; // keep track of parity

}

bitsReceived += event_bits[i];

if (bitsReceived == (wordlength)) {//this is a single stop bit

parity -= word[parityBit] + word[wordlength-1]; //don't count the stop bit and parity bit


// check for parity bit?

if (parity & 0x01){ // odd number of ones

even += word[parityBit];// 1 is correct

odd += (1-word[parityBit]);// 0 is correct

}else{

even += (1-word[parityBit]);// 0 is correct

odd += word[parityBit];// 1 is correct

}

 

bitsReceived=0;

parity=0;

}


if (bitsReceived > (wordlength)) {// overran a stop bit, pause between chars??

// this should find next/last 0 bit 

if (((char)event_lvl[i/8] & (1<<i%8)))

i++;// try starting next word from previous bit.

bitsReceived=0;

// alert();

// while(S2);

break;

}

}


if (even == wordsTotal){ //even parity

//Databits = wordLength - 3 // assuming 1 start 1 stop 1 parity

sprintf(display[1],"%d E 1  ",wordlength - 3);

DisplayString(LCD_LINE2 ,display[1]);

gParity=EVEN;

gDataBits=wordlength - 3;

gStopBits=1;

}else if (odd == wordsTotal){ // odd parity

sprintf(display[1],"%d O 1  ",wordlength - 3);

DisplayString(LCD_LINE2 ,display[1]);

gParity= ODD;

gDataBits=(char) wordlength - 3;

gStopBits=1;

}else if( ((odd+even)==wordsTotal) &&(wordsTotal==wordsPossible)){// guess no parity

sprintf(display[1],"%d N 1  ",wordlength - 2);

DisplayString(LCD_LINE2 ,display[1]);

gParity= NONE;

gDataBits= wordlength - 2;

gStopBits=1;

}

} else{

DisplayString(LCD_LINE1 ,"NoMATCH");

// DisplayString(LCD_LINE2 ,display[0]);

}



// waiting=TRUE;

// while(waiting);

// while(S2);

waiting=TRUE;

Mode = MODE_ACQUIRE;

}



/*****************************************************************************

Name: uart0_init   

Parameters: None  

Returns: None

Description: Uart0 initialization - 19200 baud, 8 data bits, 1 stop bit, no parity.

*****************************************************************************/


void uart0_init(long baudRate0,char data,char parity,char stop) {

char temp;


u0brg = (unsigned char)(((f1_CLK_SPEED/16)/baudRate0)-1); // set UART0 bit rate generator

/*

    bit rate can be calculated by:

    bit rate = ((BRG count source / 16)/baud rate) - 1


  in this example: BRG count source = f1 (12MHz - Xin in SKP16C62P)

  baud rate = 19200

  bit rate = ((12MHz/16)/19200) - 1 = 38 


    ** one has to remember that the value of BCLK does not affect BRG count source */


  ucon = 0x00; // UART transmit/receive control register 2

/*

  00000000; // transmit irq not used

  ||||||||______UART0 transmit irq cause select bit, U0IRS

    |||||||_______UART1 transmit irq cause select bit, U1IRS

    ||||||________UART0 continuous receive mode enable bit, U0RRM - set to 0 in UART mode

    |||||_________UART1 continuous receive mode enable bit, U1RRM - set to 0 in UART mode

    ||||__________CLK/CLKS select bit 0, CLKMD0 - set to 0 in UART mode

    |||___________CLK/CLKS select bit 1, CLKMD1 - set to 0 in UART mode

    ||____________Separate CTS/RTS bit, RCSP

    |_____________Reserved, set to 0 */


  u0c0 = 0x10; // UART0 transmit/receive control register 1

/*

  00010000; // f1 count source, CTS/RTS disabled, CMOS output  

  ||||||||______BRG count source select bit, CLK0

    |||||||_______BRG count source select bit, CLK1

    ||||||________CTS/RTS function select bit, CRS

    |||||_________Transmit register empty flag, TXEPT

    ||||__________CTS/RTS disable bit, CRD

    |||___________Data output select bit, NCH

    ||____________CLK polarity select bit, CKPOL - set to 0 in UART mode

    |_____________Transfer format select bit, UFORM - set to 0 in UART mode */


  u0c1 = 0x00; // UART0 transmit/receive control register 1

/*

  00000000; // disable transmit and receive 

  ||||||||______Transmit enable bit, TE

    |||||||_______Transmit buffer empty flag, TI

    ||||||________Receive enable bit, RE

    |||||_________Receive complete flag, RI

    ||||__________Reserved, set to 0

    |||___________Reserved, set to 0

    ||____________Data logic select bit, U0LCH

    |_____________Error signal output enable bit, U0ERE */


temp =0x00;

if (parity ==EVEN)

temp |= 0x60;

else if(parity ==ODD)

temp |= 0x40;

if (stop==2)

temp |= 0x10;


switch (data){

case 7:

temp |= 4;

break;

case 8:

temp |= 5;

break;

case 9:

temp |= 6;

break;

}


  u0mr = temp; // UART0 transmit/receive mode register, not reversed

/*

  00000101; // 8-bit data, internal clock, 1 stop bit, no parity

  ||||||||______Serial I/O Mode select bit, SMD0

    |||||||_______Serial I/O Mode select bit, SMD1

    ||||||________Serial I/O Mode select bit, SMD2

    |||||_________Internal/External clock select bit, CKDIR

    ||||__________Stop bit length select bit, STPS

    |||___________Odd/even parity select bit, PRY

    ||____________Parity enable bit, PRYE

    |_____________TxD, RxD I/O polarity reverse bit */


  u0tb = u0rb; // clear UART0 receive buffer by reading

  u0tb = 0; // clear UART0 transmit buffer


    DISABLE_IRQ // disable irqs before setting irq registers

s0ric = 0x04; // Enable UART0 receive interrupt, priority level 4

ENABLE_IRQ // Enable all interrupts


  u0c1 = 0x05; // UART0 transmit/receive control register 1

/*

  00000101; // enable transmit and receive 

  ||||||||______Transmit enable bit, TE

    |||||||_______Transmit buffer empty flag, TI

    ||||||________Receive enable bit, RE

    |||||_________Receive complete flag, RI

    ||||__________Reserved, set to 0

    |||___________Reserved, set to 0

    ||____________Data logic select bit, U0LCH

    |_____________Error signal output enable bit, U0ERE */

}


/*****************************************************************************

Name: uart2_init   

Parameters: None  

Returns: None

Description: Uart0 initialization - 19200 baud, 8 data bits, 1 stop bit, no parity.

*****************************************************************************/


void uart2_init(long baudRate0,char data,char parity,char stop) {

char temp;


u2brg = (unsigned char)(((f1_CLK_SPEED/16)/baudRate0)-1); // set UART0 bit rate generator

/*

    bit rate can be calculated by:

    bit rate = ((BRG count source / 16)/baud rate) - 1


  in this example: BRG count source = f1 (12MHz - Xin in SKP16C62P)

  baud rate = 19200

  bit rate = ((12MHz/16)/19200) - 1 = 38 


    ** one has to remember that the value of BCLK does not affect BRG count source */


  ucon = 0x00; // UART transmit/receive control register 2

/*

  00000000; // transmit irq not used

  ||||||||______UART0 transmit irq cause select bit, U0IRS

    |||||||_______UART1 transmit irq cause select bit, U1IRS

    ||||||________UART0 continuous receive mode enable bit, U0RRM - set to 0 in UART mode

    |||||_________UART1 continuous receive mode enable bit, U1RRM - set to 0 in UART mode

    ||||__________CLK/CLKS select bit 0, CLKMD0 - set to 0 in UART mode

    |||___________CLK/CLKS select bit 1, CLKMD1 - set to 0 in UART mode

    ||____________Separate CTS/RTS bit, RCSP

    |_____________Reserved, set to 0 */


  u2c0 = 0x10; // UART0 transmit/receive control register 1

/*

  00010000; // f1 count source, CTS/RTS disabled, CMOS output  

  ||||||||______BRG count source select bit, CLK0

    |||||||_______BRG count source select bit, CLK1

    ||||||________CTS/RTS function select bit, CRS

    |||||_________Transmit register empty flag, TXEPT

    ||||__________CTS/RTS disable bit, CRD

    |||___________Data output select bit, NCH

    ||____________CLK polarity select bit, CKPOL - set to 0 in UART mode

    |_____________Transfer format select bit, UFORM - set to 0 in UART mode */


  u2c1 = 0x00; // UART0 transmit/receive control register 1

/*

  00000000; // disable transmit and receive 

  ||||||||______Transmit enable bit, TE

    |||||||_______Transmit buffer empty flag, TI

    ||||||________Receive enable bit, RE

    |||||_________Receive complete flag, RI

    ||||__________Reserved, set to 0

    |||___________Reserved, set to 0

    ||____________Data logic select bit, U0LCH

    |_____________Error signal output enable bit, U0ERE */


temp =0x00;

if (parity ==EVEN)

temp |= 0x60;

else if(parity ==ODD)

temp |= 0x40;

if (stop==2)

temp |= 0x10;


switch (data){

case 7:

temp |= 4;

break;

case 8:

temp |= 5;

break;

case 9:

temp |= 6;

break;

}


  u2mr = temp; // UART0 transmit/receive mode register, not reversed

/*

  00000101; // 8-bit data, internal clock, 1 stop bit, no parity

  ||||||||______Serial I/O Mode select bit, SMD0

    |||||||_______Serial I/O Mode select bit, SMD1

    ||||||________Serial I/O Mode select bit, SMD2

    |||||_________Internal/External clock select bit, CKDIR

    ||||__________Stop bit length select bit, STPS

    |||___________Odd/even parity select bit, PRY

    ||____________Parity enable bit, PRYE

    |_____________TxD, RxD I/O polarity reverse bit */


  u2tb = u2rb; // clear UART0 receive buffer by reading

  u2tb = 0; // clear UART0 transmit buffer


    DISABLE_IRQ // disable irqs before setting irq registers

s2ric = 0x04; // Enable UART0 receive interrupt, priority level 4

ENABLE_IRQ // Enable all interrupts


  u2c1 = 0x05; // UART0 transmit/receive control register 1

/*

  00000101; // enable transmit and receive 

  ||||||||______Transmit enable bit, TE

    |||||||_______Transmit buffer empty flag, TI

    ||||||________Receive enable bit, RE

    |||||_________Receive complete flag, RI

    ||||__________Reserved, set to 0

    |||___________Reserved, set to 0

    ||____________Data logic select bit, U0LCH

    |_____________Error signal output enable bit, U0ERE */

}

void uart0_stop(void){

u0c1 = 0x00; // UART0 transmit/receive control register 1

}


void uart2_stop(void){

u2c1 = 0x00; // UART0 transmit/receive control register 1

}


/*****************************************************************************

Name:          

Parameters: none                     

Returns:  none      

Description:

**************************************************************************** */ 

void StartMonitoring(void)

{

uart0_init(BAUD_TABLE[guess_baud()],gDataBits,gParity,gStopBits);

uart2_init(BAUD_TABLE[guess_baud()],gDataBits,gParity,gStopBits);

text_write("Quick Coms: RS232 analyser\r\n");

}


void StopMonitoring(void)

{

uart0_stop();

uart2_stop();

menu = MENU_Detect;

configurePins;

}


/*****************************************************************************

Name:    UART0 Receive Interrupt Routine       

Parameters:  none                   

Returns:     none   

Description: Interrupt routine for UART0 receive

Reads character received from keyboard and stores U0_in variable    

*****************************************************************************/

void U0rec_ISR(void){

if (Mode= MODE_SPY){

while(ri_u0c1 == 0);   // make sure receive is complete

U0_in = (char) u0rb;      // read in received data


while(ti_u0c1 == 0); //echo on u0

u0tb = U0_in;

}

}

/*****************************************************************************

Name:    UART2 Receive Interrupt Routine       

Parameters:  none                   

Returns:     none   

Description: Interrupt routine for UART0 receive

Reads character received from keyboard and stores U0_in variable    

*****************************************************************************/

void U2rec_ISR(void){

if (Mode= MODE_SPY){

while(ri_u2c1 == 0);   // make sure receive is complete

U2_in = (char) u2rb;      // read in received data


while(ti_u0c1 == 0); //echo on u0

u0tb = U2_in;

}

}


/*****************************************************************************

Name:    text_write        

Parameters:  msg_string -> the text string to output                    

Returns:     none   

Description: The following sends a text string to the terminal program     

*****************************************************************************/

void text_write ( _far char * msg_string)

{

char i;


for (i=0; msg_string[i]; i++){ // This loop reads in the text string and 

while(ti_u0c1 == 0); //  puts it in the UART 0 transmit buffer 

u0tb = msg_string[i];

}

}