224 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			224 lines
		
	
	
		
			7.2 KiB
		
	
	
	
		
			C
		
	
	
	
#include <stdint.h>
 | 
						|
#include <stdbool.h>
 | 
						|
#include "tm4c123gh6pm.h"
 | 
						|
#include <stdio.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdlib.h>
 | 
						|
 | 
						|
 | 
						|
#define MAX_FIELD_SIZE 100
 | 
						|
volatile char nmea_sentence[MAX_FIELD_SIZE];
 | 
						|
volatile uint8_t nmea_index = 0;
 | 
						|
volatile bool nmea_ready = false;
 | 
						|
 | 
						|
void GPIO_PORT_F_init(void);
 | 
						|
void GPIO_PORT_B_init(void);
 | 
						|
void UART1_WRITE(char data);
 | 
						|
void control_leds_based_on_speed(float speed_kmh);
 | 
						|
void process_nmea_sentence(const char *nmea_sentence);
 | 
						|
 | 
						|
void GPIO_PORT_F_init(void)
 | 
						|
    {   SYSCTL_RCGC2_R |= 0x00000020;    // ENABLE CLOCK TO GPIOF
 | 
						|
        GPIO_PORTF_LOCK_R = 0x4C4F434B;  // UNLOCK COMMIT REGISTER
 | 
						|
        GPIO_PORTF_CR_R   = 0x1F;        // MAKE PORTF0 CONFIGURABLE
 | 
						|
        GPIO_PORTF_DEN_R  = 0x1F;        // SET PORTF DIGITAL ENABLE
 | 
						|
        GPIO_PORTF_DIR_R  = 0x0E;        // SET PF0, PF4 as input and PF1, PF2 and PF3 as output
 | 
						|
        GPIO_PORTF_PUR_R  = 0x11;        // PORTF PF0 and PF4 IS PULLED UP
 | 
						|
    }
 | 
						|
 | 
						|
 | 
						|
#define STRELOAD *((volatile uint32_t *) 0xE000E014)    // RELOAD VALUE REGISTER
 | 
						|
#define STCURRENT *((volatile uint32_t *) 0xE000E018)    // CURRENT VALUE REGISTER
 | 
						|
#define STCTRL *((volatile uint32_t *) 0xE000E010)    // CONTROL AND STATUS REGISTER
 | 
						|
#define COUNT_FLAG  (1 << 16)   // BIT 16 OF CSR AUTOMATICALLY SET TO 1
 | 
						|
#define ENABLE      (1 << 0)    // BIT 0 OF CSR TO ENABLE THE TIMER
 | 
						|
#define CLKINT      (1 << 2)    // BIT 2 OF CSR TO SPECIFY CPU CLOCK
 | 
						|
#define INTEN      (1 << 1)     // BIT 1 OF CSR TO ENABLE INTERRUPT
 | 
						|
#define CLOCK_HZ 16000000       // CLOCK FREQUENCY OF EK-TM4C123GXL
 | 
						|
#define SYSTICK_RELOAD_VALUE(us) ((CLOCK_HZ /1000000) * (us) - 1 ) // SYSTICK RELOAD VALUE IN MICROSECONDS BASED ON CLOCK FREQUENCY
 | 
						|
 | 
						|
#define RED_LED  0x02;
 | 
						|
#define BLUE_LED  0x04;
 | 
						|
#define GREEN_LED  0x08;
 | 
						|
volatile uint8_t LED_STATE = 0;
 | 
						|
 | 
						|
void systick_setting(void)     // SYSTICK SETUP FUNCTION
 | 
						|
{
 | 
						|
       STRELOAD = SYSTICK_RELOAD_VALUE(500000);  // SYSTICK RELOAD VALUE 500 milliseconds
 | 
						|
       STCURRENT = 0;                             //CLEARING STCURRENT REGISTER VALUE
 | 
						|
       STCTRL |= (CLKINT | ENABLE | INTEN);       // SET INTERNAL CLOCK, ENABLE THE TIMER AND INTERRUPT ENABLE
 | 
						|
}
 | 
						|
 | 
						|
void delay(int us)               //DEFINING DELAY FUNCTION
 | 
						|
{
 | 
						|
    STRELOAD = SYSTICK_RELOAD_VALUE(us) ;     // RELOAD VALUE FOR REQUIRED DELAY IN MICROSECONDS
 | 
						|
    STCURRENT = 0;                            //CLEARING STCURRENT REGISTER VALUE
 | 
						|
    STCTRL |= (CLKINT | ENABLE | INTEN );     // SET INTERNAL CLOCK, ENABLE THE TIMER
 | 
						|
    while ((STCTRL & COUNT_FLAG) == 0)        //WAIT UNTIL FLAG IS SET
 | 
						|
    {          // DO NOTHING
 | 
						|
    }
 | 
						|
    STCTRL &= 0x0;                //  STOP THE TIMER
 | 
						|
}
 | 
						|
 | 
						|
void SystickHandler(void)       //SYSTICK INTERRUPT HANDLER
 | 
						|
{
 | 
						|
    GPIO_PORTF_DATA_R ^= LED_STATE;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void GPIO_PORT_B_init(void)
 | 
						|
{
 | 
						|
    SYSCTL_RCGCGPIO_R |= 0x02;                // ENABLE CLOCK FOR GPIOB
 | 
						|
    SYSCTL_RCGCUART_R |= 0x02;                // ENABLE CLOCK FOR UART1
 | 
						|
 | 
						|
    GPIO_PORTB_DEN_R |= 0x03;                 // DIGITAL ENABLE FOR PB0 AND PB1
 | 
						|
    GPIO_PORTB_AFSEL_R |= 0x03;               // ENABLE ALTERNATE FUNCTION ON PB0,PB1
 | 
						|
 | 
						|
    GPIO_PORTB_PCTL_R = (GPIO_PORTB_PCTL_R & 0xFFFFFF00) | 0x00000011; // Set PB0, PB1 for UART
 | 
						|
 | 
						|
    UART1_CTL_R &= ~0x01;                     // DISABLE UART1 DURING SETUP
 | 
						|
    UART1_IBRD_R = 104;                       // Set integer part of baud rate (for 9600 baud at 16 MHz clock)
 | 
						|
    UART1_FBRD_R = 11;                        // Set fractional part of baud rate
 | 
						|
    UART1_LCRH_R = 0x60;                      // 8-bit, No parity, 1 stop bit
 | 
						|
    UART1_CC_R = 0x00;                        // Use system clock
 | 
						|
 | 
						|
    UART1_CTL_R |= 0x301;                     // Enable UART1, RX, and TX0
 | 
						|
    UART1_IM_R |= 0x10;
 | 
						|
    NVIC_EN0_R |= (1 << 6);
 | 
						|
}
 | 
						|
 | 
						|
void control_leds_based_on_speed(float speed_kmh)   // Control LEDs based on speed
 | 
						|
{
 | 
						|
 | 
						|
    GPIO_PORTF_DATA_R &= 0x00;                       // Clear all LED bits (assuming LEDs are connected to bits 1, 2, and 3)
 | 
						|
 | 
						|
    if (speed_kmh >= 0.0 && speed_kmh < 0.5)        // Range 0-0.5 km/h
 | 
						|
        {
 | 
						|
            //GPIO_PORTF_DATA_R |= 0x08;                   // Blink Green LED
 | 
						|
            LED_STATE = GREEN_LED;
 | 
						|
        }
 | 
						|
    else if (speed_kmh >= 0.5 && speed_kmh < 10.0)        // Range 0.5-10 km/h
 | 
						|
    {
 | 
						|
        GPIO_PORTF_DATA_R |= 0x08;                   // Green LED
 | 
						|
 | 
						|
    }
 | 
						|
    else if (speed_kmh >= 10.0 && speed_kmh < 20.0)  // Range 10-20 km/h
 | 
						|
    {
 | 
						|
        GPIO_PORTF_DATA_R |= 0x0C;                   // Cyan LED
 | 
						|
    }
 | 
						|
    else if (speed_kmh >= 20.0 && speed_kmh < 30.0)  // Range 20-30 km/h
 | 
						|
    {
 | 
						|
        GPIO_PORTF_DATA_R |= 0x04;                   // Blue LED
 | 
						|
    }
 | 
						|
    else if (speed_kmh >= 30.0 && speed_kmh < 40.0)  // Range 30-40 km/h
 | 
						|
    {
 | 
						|
        GPIO_PORTF_DATA_R |= 0x06;                   // Yellow LED (Red + Green)
 | 
						|
    }
 | 
						|
    else if (speed_kmh >= 40.0 && speed_kmh < 50.0)  // Range 40-50 km/h
 | 
						|
    {
 | 
						|
        GPIO_PORTF_DATA_R |= 0x02;                   // RED LED
 | 
						|
    }
 | 
						|
    else                                             // Above 50 km/h
 | 
						|
    {
 | 
						|
        LED_STATE = RED_LED;                         // TOGGLING RED LED
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
void nmea_sentence_process(const char *nmea_sentence)
 | 
						|
{
 | 
						|
    uint8_t i = 0;
 | 
						|
    uint8_t field_number = 0;
 | 
						|
    float speed_knots = 0.0;
 | 
						|
    float speed_kmh = 0.0;
 | 
						|
    uint8_t field_index = 0;
 | 
						|
 | 
						|
    if (nmea_sentence[0] != '$') return;  // Invalid sentence, exit
 | 
						|
 | 
						|
    if (strncmp(nmea_sentence + 1, "GPRMC", 5) == 0)
 | 
						|
    {
 | 
						|
     for (i = 6; nmea_sentence[i] != '\0'; i++)
 | 
						|
     {
 | 
						|
       if (nmea_sentence[i] == ',')
 | 
						|
       {
 | 
						|
          if (field_number == 7) // Speed in knots (field 7)
 | 
						|
          {
 | 
						|
          speed_knots = atof(nmea_sentence + i - field_index);
 | 
						|
             speed_kmh = speed_knots * 1.852;
 | 
						|
             control_leds_based_on_speed(speed_kmh);
 | 
						|
          }
 | 
						|
             field_number++;
 | 
						|
             field_index = 0;
 | 
						|
        }
 | 
						|
       else if (nmea_sentence[i] == '*')
 | 
						|
        {
 | 
						|
           break;
 | 
						|
        }
 | 
						|
       else
 | 
						|
        {
 | 
						|
          field_index++;
 | 
						|
        }
 | 
						|
      }
 | 
						|
     }
 | 
						|
    else if (strncmp(nmea_sentence + 1, "GPVTG", 5) == 0)  // Process GPVTG sentence
 | 
						|
    {
 | 
						|
     for (i = 7; nmea_sentence[i] != '\0'; i++)
 | 
						|
     {
 | 
						|
     if (nmea_sentence[i] == ',')
 | 
						|
       {
 | 
						|
       if (field_number == 6)
 | 
						|
           {
 | 
						|
           speed_knots = atof(nmea_sentence + i - field_index);
 | 
						|
           speed_kmh = speed_knots * 1.852;
 | 
						|
 | 
						|
              control_leds_based_on_speed(speed_kmh);
 | 
						|
           }
 | 
						|
              field_number++;
 | 
						|
              field_index = 0;
 | 
						|
                }
 | 
						|
     else if (nmea_sentence[i] == '*')
 | 
						|
          {
 | 
						|
           break;
 | 
						|
          }
 | 
						|
     else {
 | 
						|
           field_index++;
 | 
						|
          }
 | 
						|
         }
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
void UART1_Handler(void)
 | 
						|
{
 | 
						|
    char data = UART1_DR_R & 0xFF;
 | 
						|
    if (data == '\n' || data == '\r')
 | 
						|
    {
 | 
						|
        nmea_sentence[nmea_index] = '\0';
 | 
						|
        if (strncmp((const char *)nmea_sentence, "$GPRMC", 6) == 0)
 | 
						|
        {
 | 
						|
        nmea_ready = true;
 | 
						|
        }
 | 
						|
        nmea_index = 0;
 | 
						|
    }
 | 
						|
    else if (nmea_index < MAX_FIELD_SIZE - 1)
 | 
						|
    {
 | 
						|
        nmea_sentence[nmea_index++] = data;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
int main(void)
 | 
						|
{
 | 
						|
    GPIO_PORT_F_init();
 | 
						|
    GPIO_PORT_B_init();
 | 
						|
    systick_setting();
 | 
						|
    while (1)
 | 
						|
    {
 | 
						|
     if (nmea_ready)
 | 
						|
     {
 | 
						|
      nmea_ready = false;
 | 
						|
      nmea_sentence_process((const char *)nmea_sentence);
 | 
						|
     }
 | 
						|
    }
 | 
						|
}
 |