/* max vilimpoc's funky serial port code */

#include <pic.h> 
#include "globals.h" 

#undef SERIAL_DEBUG 

void putch(unsigned char cout) {
   unsigned int timewaster = 0;

   TXREG = cout;
   while (!TRMT);                                          // this is the fastest way of doing this.
//   for (timewaster = 0; timewaster < 100; timewaster++); // too much (100us!!) delay. just watch TRMT.
}

void putst(char * stout) {
   while((*stout) != '\0') {
      putch(*stout);
      stout = stout + 1;
   }
}

void putstc(register const char * stout) {
   while((*stout) != '\0') {
      putch(*stout);
      stout = stout + 1;
   }
}

void putdec(unsigned int iin, const char fmt) {
   unsigned char rot = 0;
   unsigned int temp = 0;

   switch(fmt) {
      case 'b':
         for (rot = 0; rot < 16; rot++) {
//       for (rot = 15; rot > 0; rot--) {       // is this a bug in HiTech C??? YES! char wraps around 
                                                // @0 and gives you about 120 chars of gobbledegook.
            if (((iin >> (15 - rot)) & 0b00000001) == 1)  { putch('1'); }
            else                                          { putch('0'); }
         }
         break;
/*
      case 'd':
         {
            temp = iin % 10;
            iin /= 10;
         }
         break;
*/
      case 'h':
         for (rot = 0; rot < 4; rot++) {
            temp = iin >> (12 - (rot * 4));
            temp = temp & 0x0F;
            if (temp > 9) {
               putch(temp += 55);
            }
            else {
               temp |= 0b00110000;
               putch((char) temp);
            }
         }
   }
}

void putlf() {
   TXEN  =  1;                   // enable transmission
   putch(13);
   putch(10);
}

void waste_time() {
   unsigned int timewaster;
   for (timewaster = 0; timewaster < 5000; timewaster++);
}

/*
 * getch() blocks until something is received / RCIF is flagged. 
 * bad programming technique, but it works: result is left in RCREG assuming calling function
 * will immediately grab RCREG contents.
 */

void getch() {
   if (OERR || FERR) {
      CREN  =  0;
      CREN  =  1;
   }

   while (!RCIF) {
   }
}

void serial_tx_init() {
   TX9   =  0;                   // 8-bits transmission
   TXIE  =  0;                   // transmit interrupt enable: false, we'll just poll
   
   TXEN  =  0;
   TXEN  =  1;
}

void serial_rx_init() {
   RX9   =  0;                   // 8-bit reception
   RCIE  =  0;                   // disable receive interrupt, polling.
   
   CREN  =  0;                   // disable reception, turn on in the function that needs to.
   //FERR, OERR watchout.
}

void serial_init() {
   SPEN  =  1;                   // set serial port enable : SPEN RCSTA<7> = 1
   TRISC =  TRISC | 0b11000000;  // set tristate TRISC<7:6> high, for both rx/tx

   SYNC  =  0;                   // asynchronous transmission mode

   BRGH  =  1;                   // Baud Rate Generator High Speed? Yes.
   SPBRG =  BRGSPEED;            // Set Baud Rate Generator to 19.2Kbps (assume clock = 4MHz)
   
   serial_tx_init();
   serial_rx_init();
}


#ifdef SERIAL_DEBUG 
main() {
   setup_interrupts();
   serial_init();
   
   putstc("test a b c.");
}
#endif