/*
 * Bit Bang Test
 *
 * Write to GP0 as if it were a UART using bit-banging. MCU is PIC12F683.
 *
 * Author: Andrew Fletcher
 * Date:   2019-10-27
 *
 */

/*
 * I/O Port usage
 *
 *
 * Debug
 *  GP0 for debug messages (TX only) 
 *
 */
 
//
// Definitions
//
#include <xc.h>
#include <stdlib.h>

/* Configuration bits */
#ifdef _PIC12F683_H_
#pragma config CP = OFF, MCLRE = ON, FOSC = INTOSCIO, WDTE = OFF
#endif

//
// global variables
//
// None

//
// ISRs
//
// None

//
// Production Functions
//

#define PIN_SER_OUT GPIObits.GP0  // which pin for serial out 
#define TMR1_BAUD_9600 18          // initial value of TMR1L to count to 128 at 9600 baud
#define WAIT_SYMBOL_TIME(X)  TMR1L = TMR1_BAUD_9600 + (X);while ((TMR1L & 0x40) == 0);TMR1L = 0x00;
// adjust the wait by X ticks to allow for differing instruction times.

void initialiseTimer1(void)
{
	// set up timer 1
    T1CONbits.TMR1CS = 0;  // use internal oscillator
    T1CONbits.T1OSCEN = 1; // enable internal oscillator
    T1CONbits.TMR1GE = 0;  // disable timer 1 gate
    T1CONbits.T1CKPS = 1;  // pre-scale 1:1
    T1CONbits.TMR1ON = 1;  // enable timer 1
}

void putcharGP0Idle(void)
{
	PIN_SER_OUT = 1; // idle high
}

void putcharGP0(unsigned char data)
{   
  TMR1L = 0;					  // initialise timer
  PIN_SER_OUT = 0;                // make start bit
  WAIT_SYMBOL_TIME(7)

  for (int i = 0; i < 8; i++)     // send 8 serial bits, LSB first
  {
    PIN_SER_OUT = data & 0x01;    // transmit 
    
    if (i == 7) {
      WAIT_SYMBOL_TIME(13)		  // last data bit
    } else {
	  WAIT_SYMBOL_TIME(18)	      // data bit
	}
	  
    data = (data >> 1);           // get next bit
  }

  PIN_SER_OUT = 1;                // make stop bit
  WAIT_SYMBOL_TIME(-1)
}

void printGP0(const char* str) 
{
	while(*str) {
		putcharGP0(*str++);
	}
}

//
// main
//
void main(void) {
unsigned long count = 0;
unsigned char str[11];

  /* I/O port configuration */
    GPIO  =  0x00;

#ifdef _PIC12F683_H_
    CMCON0 = 0x07;      /* Disable comparators */
    OSCCON = 0x60;      /* Oscillator frequency: 4MHz */
#endif

// disable all interrupts
    INTCON = 0;
  
    ANSEL =  0x00;      /* Disable A/D module */
    TRISIO = 0x3E;      /* GP0 set as OUTPUT */
    WPU = 0;            /* Disable internal pull-ups */
    OPTION_REG = 0x80;  /* Disable internal pull-ups */

    initialiseTimer1();

	putcharGP0Idle();
    /* loop forever */
    while(1) {
	 printGP0("\r\nBit Bang Test\r\n");
	 printGP0("ABCDEFGHIJKLMNOPQRSTUVWXYZ\r\n");
	 printGP0("abcdefghijklmnopqrstuvwxyz0123456789\r\n");
	 ultoa(str, count, 10); 
	 printGP0(str);
	 printGP0("\r\n"); 
	 putcharGP0Idle();
     count++;
     TMR1H = 0;
     for (int i = 0; i < 10000; i++) {  // wait a while
       while ((TMR1H & 0x80) == 0); 
     }    
	}
}
