/*
                      MSP430f2013
                    --------------
          +3,5V  --|DVCC       GND|-- DVSS
        red LED  --|P1.0      P2.6|--
            TXD  --|P1.1      P2.7|--
            RXD  --|P1.2      TEST|-- TEST/SBWTCK
        Switch2  --|P1.3     RESET|-- RST/NMI/SBWTDIO
          PWM 1  --|P1.4      P1.7|--
          PWM 2  --|P1.5      P1.6|-- green LED
                    --------------
*/

#include "msp430g2211.h"
#include "inttypes.h"
#include "stdbool.h"

// MSP430g2231 Signale / PINs
#define TXD BIT1                                                  // TXD an P1.1
#define  RXD BIT2                                                  // RXD an P1.2

// Timing for the Software UART
#define BitTime   104                                             // 9600 Baud, SMCLK=1MHz (1MHz/9600)=104
#define  BitTime_5  52                                             // BitTime / 2

/* ---- global Variables ------------------------------------------------------------------------------------ */

uint8_t BitCnt;                                                   // BitCount for the serial output
uint16_t TXByte;                                                  // TXByte sent
uint16_t RXByte;                                                  // RXByte recieved

uint16_t channel1;                                                //Analog Channel1.value //P1.6
uint16_t channel2;                                                //Analog Channel2.value //P1.7

uint16_t counter1;                                               //PWM counter 1;
uint16_t counter2;                                               //PWM counter 2;

bool digiput;                                                    //Digital Port1.0 = Channel 3
uint16_t selector;                                               //Which channel will be the next?
uint16_t selected_channel;

bool isReceiving;
bool hasReceived;

/* ---- Prototypes ------------------------------------------------------------------------------------------- */

void putChar (uint8_t c);

void main (void)
{
    WDTCTL = WDTPW + WDTHOLD;                                     // stop WDT
    BCSCTL1 = CALBC1_1MHZ;                                        // set range
    DCOCTL = CALDCO_1MHZ;                                         // SMCLK = DCO = 1MHz
    P1SEL |= TXD;                                                 // TXD connected @ Timer
    P1DIR |= TXD | BIT0 | BIT4 | BIT5;                            // TXD as Output, P1.0 as digital, P1.4 as channel1, P1.5 as channel2
    P1IES |= RXD;                                                 // RXD Hi/lo edge interrupt
    P1IFG &= ~RXD;                                                // clear RXD (flag) before enabling interrupt
    P1IE |= RXD;                                                  // Enable RXD interrupt
    
    channel1 = 0;
    channel2 = 0;
    counter1 = 0;
    counter2 = 0;
    digiput = false;
    selector = 1;
    selected_channel = 1;

//  ---- Soft. UART Timer Setup ----
    CCTL0 = OUT;                                                  // TXD Idle as Mark = '1'
    TACTL = TASSEL_2 + MC_2;                                      // SMCLK, continuous mode

    isReceiving = false;                                          // set initial values
    hasReceived = false;

    __bis_SR_register (GIE);                                      // interrupts enabled

	putChar(42); //Send ON-State

    while (1) {
        if (hasReceived) {                                        // Char recieved ?
            hasReceived = false;  
            
            if(selector != 2){
                                            // clear "hasReceived" flag
            putChar (23);  //Send ACK
            
            switch(RXByte){
            	case 0:{
            		putChar(42);
            	}break;
            	
            	case 1:{ //Analog channel 1
            		selected_channel = 1;
            		selector = 2;	
            	}break;
            	
            	case 2:{ //Analog channel 2
            		selected_channel = 2;
            		selector = 2;	
            	}break;
            	
            	case 3:{//Digital Channel
            		selected_channel = 3;
            		selector = 2;	
            	}break;
            	
            	case 4:{ //Reset analog
            		channel1 = 0;
            		channel2 = 0;
            		selector = 2;
            	}break;
            	
            	case 5:{ //Reset all
            		channel1 = 0;
            		channel2 = 0;
            		digiput = 1;
            		selector = 2;
            	}break;
            }
           }else{
           	switch(selected_channel){
           		case 1:{
           			channel1 = RXByte;
           		}break;
           		
           		case 2:{
           			channel2 = RXByte;
           		}break;
           		
           		case 3:{
        			digiput = RXByte;
        			
           		}
           	}
           	selector = 1;
            }
        }
        if (~hasReceived) __bis_SR_register (CPUOFF + GIE);
        
        //Handle digital output
        if(digiput){
        	P1OUT &= ~(BIT0);
        }else{
        	P1OUT |= BIT0;	
        }
        
        //Handle analog channel 1
        counter1++;
        if(counter1 == 0){
        	P1OUT |= BIT4;	
        }
        if(counter1 == channel1){
        	P1OUT &= ~(BIT4);	
        }
        if(counter1 == 255){
        	counter1 = 0;	
        }
        
        //Handle analog channel 2
        counter2++;
        if(counter2 == 0){
        	P1OUT |= BIT5;	
        }
        if(counter2 == channel2){
        	P1OUT &= ~(BIT5);	
        }
        if(counter2 == 255){
        	counter2 = 0;	
        }
        
    }
}


/* ---- simple putChar --------------------------------------------------------------------------------------- */

void putChar (uint8_t c)
{
    while (isReceiving);                                          // Receiver busy ?
    BitCnt = 0xA;                                                 // BitCounter 8 BIT + Start/Stop BIT
    CCR0 = TAR;                                                   // Compare Register initialisieren
    CCR0 += BitTime;                                              // Add up BIT time
    TXByte = (c |= 0x100);                                        // Add Stop BIT to TXByte (logic 1)
    TXByte <<= 1;                                                 // Add Start BIT to TXByte (logic 0)
    CCTL0 = CCIS0 + OUTMOD0 + CCIE;                               // Set signal, intial value, enable interrupts
    while (CCTL0 & CCIE);                                         // Wait for all BIT to be sent
}

/* ---- Start receive timer and disable any current transmission --------------------------------------------- */

#pragma vector=PORT1_VECTOR
__interrupt void Port_1 (void)
{
    isReceiving = true;
    P1IE &= ~RXD;                                                 // Disable RXD interrupt
    P1IFG &= ~RXD;                                                // Clear RXD IFG (interrupt flag)
    TACTL = TASSEL_2 + MC_2;                                      // SMCLK, continuous mode
    CCR0 = TAR;                                                   // Init Compare Register
    CCR0 += BitTime_5;                                            // Add up half BIT time
    CCTL0 = OUTMOD1 + CCIE;                                       // Disable TX and enable interrupts
    RXByte = 0;                                                   // init RXByte
    BitCnt = 0x9;                                                 // BitCounter 8 BIT + ST
}

/* ---- Timer interrupt routine, transmitting and receiving bytes. ------------------------------------------- */

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
    if (!isReceiving) {
        CCR0 += BitTime;                                          // Add up BIT time
        if (BitCnt == 0) {                                        // If all BITs are sent
            CCTL0 &= ~ CCIE;                                      // Disable interrupt
        } else {
            CCTL0 |= OUTMOD2;                                     // TX BIT = 0
            if (TXByte & 0x01) CCTL0 &= ~ OUTMOD2;                // If it should be 1, set it to 1
            TXByte >>= 1;
            BitCnt --;
        }
    } else {
        CCR0 += BitTime;                                          // Add up BIT time
        if (BitCnt == 0) {
            CCTL0 &= ~ CCIE;                                      // Disable interrupt
            isReceiving = false;
            P1IFG &= ~RXD;                                        // clear RXD IFG (interrupt flag)
            P1IE |= RXD;                                          // enable RXD interrupt
            if ((RXByte & 0x201) == 0x200) {                      // check START/STOP BIT
                RXByte >>= 1;                                     // Remove START BIT
                RXByte &= 0xFF;                                   // Remove STOP BIT
                hasReceived = true;
            }
            __bic_SR_register_on_exit (CPUOFF);                   // Enable CPU so the main while loop continues
        } else {
            if ((P1IN & RXD) == RXD) RXByte |= 0x400;             // Set the value in RXByte If bit is set
            RXByte >>= 1;                                         // Shift BIT's
            BitCnt --;
        }
    }
}
