#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "tm4c123gh6pm.h"
//#include "inc/tm4c123gh6pm.h"
#include <string.h>
#define RED_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 1*4)))
#define GREEN1_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 3*4)))
#define BLUE_LED (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 2*4)))
#define GREEN2_LED (*((volatile uint32_t *)(0x42000000 + (0x400053FC-0x40000000)*32 + 6*4)))
#define YELLOW_LED (*((volatile uint32_t *)(0x42000000 + (0x400053FC-0x40000000)*32 + 7*4)))
#define PUSH_BUTTON1 (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 0*4)))
#define PUSH_BUTTON2 (*((volatile uint32_t *)(0x42000000 + (0x400253FC-0x40000000)*32 + 4*4)))
#define PUSH_BUTTON3 (*((volatile uint32_t *)(0x42000000 + (0x400243FC-0x40000000)*32 + 1*4)))
#define PUSH_BUTTON4 (*((volatile uint32_t *)(0x42000000 + (0x400243FC-0x40000000)*32 + 3*4)))
uint8_t leds;
void waitMicrosecond(uint32_t us)
{
// Approx clocks per us
__asm("WMS_LOOP0: MOV R1, #6"); // 1
__asm("WMS_LOOP1: SUB R1, #1"); // 6
__asm(" CBZ R1, WMS_DONE1"); // 5+1*3
__asm(" NOP"); // 5
__asm(" B WMS_LOOP1"); // 5*3
__asm("WMS_DONE1: SUB R0, #1"); // 1
__asm(" CBZ R0, WMS_DONE0"); // 1
__asm(" B WMS_LOOP0"); // 1*3
__asm("WMS_DONE0:"); // ---
// 40 clocks/us + error
}
void setRW(uint8_t mode)
{
if (mode==0)
{I2C1_MSA_R &= ~(1<<0);}
else
{I2C1_MSA_R |= 0x01;}
}
void init_hw()
{
SYSCTL_RCC_R = SYSCTL_RCC_XTAL_16MHZ | SYSCTL_RCC_OSCSRC_MAIN | SYSCTL_RCC_USESYSDIV | (4 << SYSCTL_RCC_SYSDIV_S);
SYSCTL_RCGC2_R = SYSCTL_RCGC2_GPIOF|SYSCTL_RCGC2_GPIOB| SYSCTL_RCGC2_GPIOA |SYSCTL_RCGC2_GPIOE;
GPIO_PORTF_LOCK_R = 0x4C4F434B;
GPIO_PORTF_CR_R = 0x1F;
GPIO_PORTF_DIR_R |= 0x0E; // make bit 1 an outputs
GPIO_PORTF_DR2R_R |= 0x0E; // set drive strength to 2mA (not needed since default configuration -- for clarity)
GPIO_PORTF_PUR_R = 0x11; // enable internal pull-up for push button
GPIO_PORTF_DEN_R |= 0x1F; // enable LED
GPIO_PORTE_DIR_R |= 0x00; // make bit 1 an outputs
GPIO_PORTE_PUR_R = 0x0A; // enable internal pull-up for push button
GPIO_PORTE_DEN_R |= 0x0A; // enable LED
GPIO_PORTB_DIR_R |= 0xC0; // YELLOW and GREEN
GPIO_PORTB_DR2R_R |= 0xC0; // set drive strength to 2mA (not needed since default configuration -- for clarity)
GPIO_PORTB_DEN_R |= 0xC0; // enable LED
// Configure UART0 pins
SYSCTL_RCGCUART_R |= SYSCTL_RCGCUART_R0; // turn-on UART0, leave other uarts in same status
GPIO_PORTA_DEN_R |= 3; // default, added for clarity
GPIO_PORTA_AFSEL_R |= 3; // default, added for clarity
GPIO_PORTA_PCTL_R |= GPIO_PCTL_PA1_U0TX | GPIO_PCTL_PA0_U0RX;
// Configure UART0 to 115200 baud, 8N1 format (must be 3 clocks from clock enable and config writes)
UART0_CTL_R = 0; // turn-off UART0 to allow safe programming
UART0_CC_R = UART_CC_CS_SYSCLK; // use system clock (40 MHz)
UART0_IBRD_R = 21; // r = 40 MHz / (Nx115.2kHz), set floor(r)=21, where N=16
UART0_FBRD_R = 45; // round(fract(r)*64)=45
UART0_LCRH_R = UART_LCRH_WLEN_8 | UART_LCRH_FEN; // configure for 8N1 w/ 16-level FIFO
UART0_CTL_R = UART_CTL_TXE | UART_CTL_RXE | UART_CTL_UARTEN; // enable TX, RX, and module
//Configure I2C module 1
SYSCTL_RCGCI2C_R |= SYSCTL_RCGCI2C_R1;
GPIO_PORTA_DEN_R |= 0xC0;
GPIO_PORTA_AFSEL_R |= 0xC0;
GPIO_PORTA_ODR_R |= 0x80;
GPIO_PORTA_PCTL_R |= GPIO_PCTL_PA7_I2C1SDA | GPIO_PCTL_PA6_I2C1SCL;
I2C1_MCR_R |= I2C_MCR_MFE;
//TPR = (System Clock/(2*(SCL_LP + SCL_HP)*SCL_CLK))-1;
//TPR = (20MHz/(2*(6+4)*100000))-1;
//TPR = 9
I2C1_MTPR_R= 19; // Decimal Value
I2C1_MSA_R=(0x20<<1); // Set Slave address
setRW(0);
}
char* itoa(int i)
{
char b[100];
char const digit[] = "0123456789";
char* p = b;
if(i<0){
*p++ = '-';
i *= -1;
}
int shifter = i;
do{ //Move to where representation ends
++p;
shifter = shifter/10;
}while(shifter);
*p = '\0';
do{ //Move back, inserting digits as u go
*--p = digit[i%10];
i = i/10;
}while(i);
return b;
}
void putcUart0(char c)
{
while (UART0_FR_R & UART_FR_TXFF);
UART0_DR_R = c;
}
// Blocking function that writes a string when the UART buffer is not full
void putsUart0(char* str)
{
int i;
for (i = 0; i < strlen(str); i++)
putcUart0(str[i]);
}
// Blocking function that returns with serial data once the buffer is not empty
uint8_t readPbs()
{
return ((!PUSH_BUTTON1)+((!PUSH_BUTTON2)<<1)+((!PUSH_BUTTON3)<<2)+((!PUSH_BUTTON4)<<3));
}
void writeByte(uint8_t dataByte, uint8_t conditions)
{
I2C1_MDR_R= dataByte;
I2C1_MCS_R=conditions;
while((I2C1_MCS_R & I2C_MCS_BUSBSY)!=0); // Controller is Busy
if ((I2C1_MCS_R & (1<<3))!=0)
putsUart0("The Data was not Acknowledged\n\r");
if ((I2C1_MCS_R & (1<<2))!=0)
putsUart0("The Address was not Acknowledged\n\r");
if((I2C1_MCS_R & 2)!=0)
{
if((I2C1_MCS_R &(1<<4))!=0)
putsUart0("The Controller Lost Arbitration\n\r");
if ((I2C1_MCS_R & (1<<3))!=0)
putsUart0("The Data was not Acknowledged\n\r");
if ((I2C1_MCS_R & (1<<2))!=0)
putsUart0("The Address was not Acknowledged\n\r");
else
{
putsUart0("ERROR TRANSMITTING\n\r");
I2C1_MCS_R = (1<<2);
while((I2C1_MCS_R & 1)!=0); // Controller is Busy
}
}
}
int main(void)
{
init_hw();
RED_LED=0;
putsUart0("I2C....\n\r");
writeByte(0x00,3); //Send register address "START and RUN"
writeByte(0x00,5); //Set all data as output "RUN and STOP"
while(1)
{
writeByte(0x09,3);
writeByte(0xFF,5);
//waitMicrosecond(1000);
}
while(1);
return 0;
}