123

Dependencies:   mbed

Fork of LG by igor Apu

DeviceUserPort.c

Committer:
Kovalev_D
Date:
2016-10-19
Revision:
197:7a05523bf588
Parent:
183:c7a9c309086c

File content as of revision 197:7a05523bf588:

#include "Device.h"

extern Device device;
extern unsigned int SystemCoreClock1;

void InitUserPortDefaultSettings(void) {
  device.user.port.settings.mode = 0;     //Baud rate usage: 0 - accept baud rate change; 1 - always 921600
  device.user.port.settings.baud = 38400;
}

void InitUserPortState(void) {
  device.user.port.state.mode = device.user.port.settings.mode;
  device.user.port.state.baud = userSelectBaudRate(device.user.port.settings.baud);
}

void DeviceStartUserPort(void)
{ 
  LPC_PINCON->PINSEL4 &= ~0x0000000F;
  LPC_PINCON->PINSEL4 |= 0x0000000A;  //Enable RxD1 P2.1, TxD1 P2.0
  
  userSetBaudRate(device.user.port.state.baud);
  
  device.controller.uart[1].state.FCR = 0x03;
  LPC_UART1->FCR = device.controller.uart[1].state.FCR; //Enable and reset TX and RX FIFO.

  /*
  //Uncomment to use interrupts
  //NVIC_EnableIRQ(UART1_IRQn);
  //LPC_UART1->IER = IER_RBR | IER_THRE | IER_RLS;  //Enable UART1 interrupt
  */
}

uint32_t userSelectBaudRate(uint32_t baud) {
  if (device.user.port.state.mode == 1)
    return 921600;
  else
    return baud;
}

void userSetBaudRate(uint32_t baud) {
  baud = userSelectBaudRate(baud);
  //Peripheral clock of UART1
  uint32_t pclkdiv = (LPC_SC->PCLKSEL0 >> 8) & 0x03;    //Bits 8,9 are for UART1
  uint32_t pclk;
  switch ( pclkdiv ) {
      case 0x00:
      default:
        pclk = SystemCoreClock1/4;
        break;
      case 0x01:
        pclk = SystemCoreClock1;
        break; 
      case 0x02:
        pclk = SystemCoreClock1/2;
        break; 
      case 0x03:
        pclk = SystemCoreClock1/8;
        break;
  }  
  //Divider
  uint32_t Fdiv = ( pclk / 16 ) / baud;
  //Enable divider write
  device.controller.uart[1].state.LCR = 0x83;
  LPC_UART1->LCR = device.controller.uart[1].state.LCR; //8 bits, no Parity, 1 Stop bit
  //Write divider hi byte
  device.controller.uart[1].state.DLM = Fdiv / 256;
  LPC_UART1->DLM = device.controller.uart[1].state.DLM;
  //Write divider lo byte
  device.controller.uart[1].state.DLL = Fdiv % 256;
  LPC_UART1->DLL = device.controller.uart[1].state.DLL;
  //Disable divider write
  device.controller.uart[1].state.LCR = 0x03;
  LPC_UART1->LCR = device.controller.uart[1].state.LCR; //DLAB = 0
  
  device.user.port.state.baud = baud;
  
  #ifdef DEBUG_USER_BAUD
  sprintf(device.service.buffer, "userSetBaudRate(%06d)\r\n", baud); WriteConcole();
  #endif
}

void userReceive(void){
  if (LPC_UART1->LSR & 0x01) {
    device.user.request.buffer.data[device.user.request.buffer.end] = LPC_UART1->RBR;
    device.user.request.buffer.end = (device.user.request.buffer.end + 1) % InputBufferSize;
    device.user.request.buffer.empty = 0;
    device.user.decoder.canceled = 0; //Clear decode canceled flag
  }
}

void userTransmit(void){
  if (device.user.response.ready) {
    if (device.user.response.type == RESPONSE_DELAYED) {
      if (!device.user.response.triggered) return;     
    }
    
    if (device.user.response.buffer.position < device.user.response.buffer.count) {
      if (LPC_UART1->LSR & 0x20) {
        LPC_UART1->THR = device.user.response.buffer.data[device.user.response.buffer.position];
        device.user.response.buffer.position++;
        if (device.user.response.buffer.position == device.user.response.buffer.count){
          device.user.response.ready = 0;
          if (device.user.response.type == RESPONSE_PERIODIC) {
            device.user.response.enabled = 1; //next response encoding required
          }
          if (device.user.response.type == RESPONSE_DELAYED) {
            device.user.response.triggered = 0; //Clear transmission flag, wait next trigger event. Here ok - transmit response in multiple passes!
          }
          device.user.response.buffer.count = 0;
          device.user.response.buffer.position = 0;
        }
      }
    }
  }
}

//
//Compatibility section
//
uint8_t var_SRgR(void) {
  //SysRgR
  //    Unused 3 bits: => xxxxx000
  //    Hardware: transmitter rate = receiver rate => xxxx1000
  //    Sending response, so transmitter enabled, no case => 1xxx1000
  //    Request received, so receiver enabled, no case => 11xx1000
  uint8_t res;
  switch (device.user.port.state.baud) {
    case  38400: res = 0xc8; break; //11001000
    case 115200: res = 0xd8; break; //11011000
    case 460800: res = 0xe8; break; //11101000
    case 921600: res = 0xf8; break; //11111000
    default:     res = 0xc8;        //11001000 - 38400
  }
  return res;
}

//
//Not used section
//  Communication using interrupt
/*
#define IER_RBR     0x01
#define IER_THRE    0x02
#define IER_RLS     0x04

#define IIR_PEND    0x01
#define IIR_RLS     0x03
#define IIR_RDA     0x02
#define IIR_CTI     0x06
#define IIR_THRE    0x01

#define LSR_RDR     0x01
#define LSR_OE      0x02
#define LSR_PE      0x04
#define LSR_FE      0x08
#define LSR_BI      0x10
#define LSR_THRE    0x20
#define LSR_TEMT    0x40
#define LSR_RXFE    0x80

void UART1Send(void)
{
  uint8_t pos = 0;
  while (device.host.response.buffer.count != pos ) {
    //THRE status, contain valid data
    while ( !(device.host.port.TxEmpty & 0x01) ); 
    LPC_UART1->THR = device.host.response.buffer.data[pos];
    device.host.port.TxEmpty = 0; //not empty in the THR until it shifts out
    pos++;
  }
  device.host.response.buffer.count = 0;
}

//Not used 
__irq void UART1_IRQHandler (void)
{
  uint8_t IIRValue, LSRValue;
  uint8_t Dummy = Dummy;
    
  IIRValue = LPC_UART1->IIR;
    
  IIRValue >>= 1;            //skip pending bit in IIR
  IIRValue &= 0x07;          //check bit 1~3, interrupt identification
  if ( IIRValue == IIR_RLS ) // Receive Line Status
  {
    LSRValue = LPC_UART1->LSR;
    //Receive Line Status
    if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
    {
      //There are errors or break interrupt
      //Read LSR will clear the interrupt
      device.host.port.status = LSRValue;
      Dummy = LPC_UART1->RBR;//Dummy read on RX to clear interrupt, then bail out
      return;
    }
    if ( LSRValue & LSR_RDR )//Receive Data Ready
    {
      //If no error on RLS, normal ready, save into the data buffer.
      //Note: read RBR will clear the interrupt
      device.host.request.buffer.data[device.host.request.buffer.end] = LPC_UART1->RBR;
      device.host.request.buffer.end = (device.host.request.buffer.end + 1) % InputBufferSize;
    }
  }
  else if ( IIRValue == IIR_RDA )   //Receive Data Available
  {
    device.host.request.buffer.data[device.host.request.buffer.end] = LPC_UART1->RBR;
    device.host.request.buffer.end = (device.host.request.buffer.end + 1) % InputBufferSize;
  }
  else if ( IIRValue == IIR_CTI )   //Character timeout indicator
  {
    //Character Time-out indicator
    device.host.port.status |= 0x100; //Bit 9 as the CTI error
  }
  else if ( IIRValue == IIR_THRE )    //THRE, transmit holding register empty
  {
    //THRE interrupt
    LSRValue = LPC_UART1->LSR;        //Check status in the LSR to see if valid data in U0THR or not
    if ( LSRValue & LSR_THRE )
    {
      device.host.port.TxEmpty = 1;
    }
    else
    {
      device.host.port.TxEmpty = 0;
    }
  }
}*/