// Copyright (c) 2001-2004 Rowley Associates Limited.
//
// This file may be distributed under the terms of the License Agreement
// provided with this software.
//
// THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
////////////////////////////////////////////////////////////////////////////////
//
//                        MPE ARM7DK UART Example
//
// Description
// -----------
// This example demonstrates configuring, reading and writing to a UART. It also 
// demonstrates how to get printf output over the UART by implementing 
// __putchar.
//
// To see output:
//   - Connect serial cable the MPE ARM7DK board to your host computer.
//   - Open CrossStudio's "Terminal Emulator Window". Configure it to 4800 baud, 
//     8 data bits, no parity, 2 stop bits. Click "Connect" to start the
//     terminal emulator window.
//
////////////////////////////////////////////////////////////////////////////////

#define PROCESSOR_CLOCK_FREQUENCY 24000000

/* UART Registers */
#define RBR0 (*(volatile unsigned long *)0xFFFF0000)
#define THR0 (*(volatile unsigned long *)0xFFFF0000)
#define DLL0 (*(volatile unsigned long *)0xFFFF0000)
#define IER0 (*(volatile unsigned long *)0xFFFF0004)
#define DLM0 (*(volatile unsigned long *)0xFFFF0004)
#define IIR0 (*(volatile unsigned long *)0xFFFF0008)
#define LCR0 (*(volatile unsigned long *)0xFFFF000C)
#define MCR0 (*(volatile unsigned long *)0xFFFF0010)
#define LSR0 (*(volatile unsigned long *)0xFFFF0014)
#define MSR0 (*(volatile unsigned long *)0xFFFF0018)
#define SCR0 (*(volatile unsigned long *)0xFFFF001C)

#define RBR1 (*(volatile unsigned long *)0xFFFF0400)
#define THR1 (*(volatile unsigned long *)0xFFFF0400)
#define DLL1 (*(volatile unsigned long *)0xFFFF0400)
#define IER1 (*(volatile unsigned long *)0xFFFF0404)
#define DLM1 (*(volatile unsigned long *)0xFFFF0404)
#define IIR1 (*(volatile unsigned long *)0xFFFF0408)
#define LCR1 (*(volatile unsigned long *)0xFFFF040C)
#define MCR1 (*(volatile unsigned long *)0xFFFF0410)
#define LSR1 (*(volatile unsigned long *)0xFFFF0414)
#define MSR1 (*(volatile unsigned long *)0xFFFF0418)
#define SCR1 (*(volatile unsigned long *)0xFFFF041C)

#define RBR2 (*(volatile unsigned long *)0xFFFF0800)
#define THR2 (*(volatile unsigned long *)0xFFFF0800)
#define DLL2 (*(volatile unsigned long *)0xFFFF0800)
#define IER2 (*(volatile unsigned long *)0xFFFF0804)
#define DLM2 (*(volatile unsigned long *)0xFFFF0804)
#define IIR2 (*(volatile unsigned long *)0xFFFF0808)
#define LCR2 (*(volatile unsigned long *)0xFFFF080C)
#define MCR2 (*(volatile unsigned long *)0xFFFF0810)
#define LSR2 (*(volatile unsigned long *)0xFFFF0814)
#define MSR2 (*(volatile unsigned long *)0xFFFF0818)
#define SCR2 (*(volatile unsigned long *)0xFFFF081C)

#define SIR_CTLR (*(volatile unsigned long *)0xFFFF0C00)

static void
UARTInitialize(unsigned long baudrate)
{
  unsigned short divisor = PROCESSOR_CLOCK_FREQUENCY / (16 * baudrate);
  /* 8 bit data, 2 stop bits, no parity */
  LCR2 = 0x7; 
  /* Setup Divisor */
  LCR2 |= 0x80; 
  DLL2 = divisor & 0xFF;
  DLM2 = (divisor >> 8) & 0xFF;
  LCR2 &= ~0x80;
  /* Run IrDA SIR in UART mode */
  SIR_CTLR = 0x0; 
}

static void
UARTWriteChar(char ch)
{
  /* Wait for Transmitter Holding Register to empty */
  while (!(LSR2 & (1 << 5)));
  /* Transmit data */
  THR2 = ch;
}

static char
UARTReadChar(void)
{
  /* Wait for Receiver Buffer Register to fill */
  while (!(LSR2 & (1 << 0)));
  /* Read data */
  return RBR2;
}

static int
UARTReadAvailable(void)
{
  return LSR2 & (1 << 0);
}

void __putchar(int ch)
{
  if (ch == '\n')
    UARTWriteChar('\r');
  UARTWriteChar(ch);
}
int
main(void)
{
  int i;
  UARTInitialize(4800); 
  for (i = 0;; ++i)
    {
      printf("Hello World (%d)\n", i);
      if (UARTReadAvailable())
        {
          char ch = UARTReadChar();
          if (ch == 'q' || ch == 'Q')
            break;
          printf("Key \'%c\' pressed\n", ch);
        }
    }
  printf("Quit\n");
  return 0; 
}

