/************************************************************************************
 SerialTx
 CFunction to create additional Tx only serial outputs for the Micromite
 Geoff Graham, May 2015

 usage:  r = SerialTx(pin, baud-rate, string)
 where   pin                is the output pin
         baud-rate          is the desired transmit speed (maximum 38400 at 40MHz)
         string             is the string of characters to send
         r                  is the return value which is always zero
 *************************************************************************************/

#define _SUPPRESS_PLIB_WARNING                                      // required for XC1.33  Later compiler versions will need PLIB to be installed
#include <plib.h>                                                   // the pre Harmony peripheral libraries
#include "CFunctions.h"                                             // MMBasic API definitions

void Delay(unsigned int ticks);

long long int main(unsigned int *pin, unsigned int *BaudRate, char *string) {
    unsigned int ticks;
    volatile unsigned int *PortSet, *PortClr;                       // the PIC32 register to control the I/O pin
    unsigned char mask;
    int pinbit, count = 0;

    ticks = ((CurrentCpuSpeed / 2) / *BaudRate) - 5;                // calculate the core timer ticks for each bit
    ExtCfg(*pin, EXT_DIG_OUT, 0);                                   // configure the pin as an output
    ExtSet(*pin, 1);                                                // set the output high
    PortSet = GetPortAddr(*pin, LATSET);                            // get the I/O registers
    PortClr = GetPortAddr(*pin, LATCLR);
    pinbit = GetPinBit(*pin);                                       // get the bit in the port register

    while(count++ < string[0]) {
        *PortClr = 1 << pinbit;                                     // send the start bit
        Delay(ticks);                                               // wait for the specified baud rate timing
        for (mask = 0x01; mask > 0; mask <<= 1) {
            if(string[count] & mask)                                // check the bit to send
                *PortSet = 1 << pinbit;                             // send 1
            else
                *PortClr = 1 << pinbit;                             // send 0
            Delay(ticks);                                           // wait for the specified baud rate timing
      }
      *PortSet = 1 << pinbit;                                       // send the stop bit
      Delay(ticks);                                                 // wait for the specified baud rate timing
    }
    return 0;
}


// delay for a certain number of core timer ticks (one tick every 50nS at 40MHz CPU speed, 100nS at 20MHz, etc)
void Delay(unsigned int ticks) {
    unsigned int current_ticks = 0;
     asm volatile("mtc0   %0, $9": "+r"(current_ticks));            // set the core timer to zero
     do {
         asm volatile("mfc0   %0, $9" : "=r"(current_ticks));       // get the core timer ticks
     } while(current_ticks < ticks);
}
