#include <stdint.h>
#include "itoa.h"
#include "inc/LPC214x.h"
#include "armint.h"
#include "config.h"
#include "hdr/hdr_scb.h"
#include "hdr/hdr_mam.h"
#include "system.h"
#include "czekaj.h"
#include "hd44780.h"
#include <string.h> // memcpy
#include "type.h"
#include "armVIC.h"
//#include "console.h"
//#include "usbdebug.h"
#include "usbapi.h"
#include "serial_fifo.h"
//a
#define INT_VECT_NUM 0
#define IRQ_MASK 0x00000080
#define BAUD_RATE 115200
#define INT_IN_EP 0x81
#define BULK_OUT_EP 0x05
#define BULK_IN_EP 0x82
#define MAX_PACKET_SIZE 64
#define LE_WORD(x) ((x)&0xFF),((x)>>8)
// CDC definitions
#define CS_INTERFACE 0x24
#define CS_ENDPOINT 0x25
#define SET_LINE_CODING 0x20
#define GET_LINE_CODING 0x21
#define SET_CONTROL_LINE_STATE 0x22
// data structure for GET_LINE_CODING / SET_LINE_CODING class requests
typedef struct {
U32 dwDTERate;
U8 bCharFormat;
U8 bParityType;
U8 bDataBits;
} TLineCoding;
static TLineCoding LineCoding = {115200, 0, 0, 8};
static U8 abBulkBuf[64];
static U8 abClassReqData[8];
static U8 txdata[VCOM_FIFO_SIZE];
static U8 rxdata[VCOM_FIFO_SIZE];
static fifo_t txfifo;
static fifo_t rxfifo;
// forward declaration of interrupt handler
static void USBIntHandler(void) __attribute__ ((interrupt("IRQ")));
/*
+=============================================================================+
| module variables
+=============================================================================+
*/
/*
+=============================================================================+
| local functions' declarations
+=============================================================================+
*/
uint8_t counter;
static const U8 abDescriptors[] = {
// device descriptor
0x12,
DESC_DEVICE,
LE_WORD(0x0101), // bcdUSB
0x02, // bDeviceClass
0x00, // bDeviceSubClass
0x00, // bDeviceProtocol
MAX_PACKET_SIZE0, // bMaxPacketSize
LE_WORD(0xFFFF), // idVendor
LE_WORD(0x0005), // idProduct
LE_WORD(0x0100), // bcdDevice
0x01, // iManufacturer
0x02, // iProduct
0x03, // iSerialNumber
0x01, // bNumConfigurations
// configuration descriptor
0x09,
DESC_CONFIGURATION,
LE_WORD(67), // wTotalLength
0x02, // bNumInterfaces
0x01, // bConfigurationValue
0x00, // iConfiguration
0xC0, // bmAttributes
0x32, // bMaxPower
// control class interface
0x09,
DESC_INTERFACE,
0x00, // bInterfaceNumber
0x00, // bAlternateSetting
0x01, // bNumEndPoints
0x02, // bInterfaceClass
0x02, // bInterfaceSubClass
0x01, // bInterfaceProtocol, linux requires value of 1 for the cdc_acm module
0x00, // iInterface
// header functional descriptor
0x05,
CS_INTERFACE,
0x00,
LE_WORD(0x0110),
// call management functional descriptor
0x05,
CS_INTERFACE,
0x01,
0x01, // bmCapabilities = device handles call management
0x01, // bDataInterface
// ACM functional descriptor
0x04,
CS_INTERFACE,
0x02,
0x02, // bmCapabilities
// union functional descriptor
0x05,
CS_INTERFACE,
0x06,
0x00, // bMasterInterface
0x01, // bSlaveInterface0
// notification EP
0x07,
DESC_ENDPOINT,
INT_IN_EP, // bEndpointAddress
0x03, // bmAttributes = intr
LE_WORD(8), // wMaxPacketSize
0x0A, // bInterval
// data class interface descriptor
0x09,
DESC_INTERFACE,
0x01, // bInterfaceNumber
0x00, // bAlternateSetting
0x02, // bNumEndPoints
0x0A, // bInterfaceClass = data
0x00, // bInterfaceSubClass
0x00, // bInterfaceProtocol
0x00, // iInterface
// data EP OUT
0x07,
DESC_ENDPOINT,
BULK_OUT_EP, // bEndpointAddress
0x02, // bmAttributes = bulk
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
0x00, // bInterval
// data EP in
0x07,
DESC_ENDPOINT,
BULK_IN_EP, // bEndpointAddress
0x02, // bmAttributes = bulk
LE_WORD(MAX_PACKET_SIZE), // wMaxPacketSize
0x00, // bInterval
// string descriptors
0x04,
DESC_STRING,
LE_WORD(0x0409),
0x0E,
DESC_STRING,
'L', 0, 'P', 0, 'C', 0, 'U', 0, 'S', 0, 'B', 0,
0x14,
DESC_STRING,
'U', 0, 'S', 0, 'B', 0, 'S', 0, 'e', 0, 'r', 0, 'i', 0, 'a', 0, 'l', 0,
0x12,
DESC_STRING,
'D', 0, 'E', 0, 'A', 0, 'D', 0, 'C', 0, '0', 0, 'D', 0, 'E', 0,
// terminating zero
0
};
/**
Local function to handle incoming bulk data
@param [in] bEP
@param [in] bEPStatus
*/
static void BulkOut(U8 bEP, U8 bEPStatus)
{
int i, iLen;
if (fifo_free(&rxfifo) < MAX_PACKET_SIZE) {
// may not fit into fifo
return;
}
// get data from USB into intermediate buffer
iLen = USBHwEPRead(bEP, abBulkBuf, sizeof(abBulkBuf));
for (i = 0; i < iLen; i++) {
// put into FIFO
if (!fifo_put(&rxfifo, abBulkBuf[i])) {
// overflow... :(
ASSERT(FALSE);
break;
}
}
}
/**
Local function to handle outgoing bulk data
@param [in] bEP
@param [in] bEPStatus
*/
static void BulkIn(U8 bEP, U8 bEPStatus)
{
int i, iLen;
if (fifo_avail(&txfifo) == 0) {
// no more data, disable further NAK interrupts until next USB frame
USBHwNakIntEnable(0);
return;
}
// get bytes from transmit FIFO into intermediate buffer
for (i = 0; i < MAX_PACKET_SIZE; i++) {
if (!fifo_get(&txfifo, &abBulkBuf[i])) {
break;
}
}
iLen = i;
// send over USB
if (iLen > 0) {
USBHwEPWrite(bEP, abBulkBuf, iLen);
}
}
/**
Local function to handle the USB-CDC class requests
@param [in] pSetup
@param [out] piLen
@param [out] ppbData
*/
static BOOL HandleClassRequest(TSetupPacket *pSetup, int *piLen, U8 **ppbData)
{
switch (pSetup->bRequest) {
// set line coding
case SET_LINE_CODING:
DBG("SET_LINE_CODING\n");
memcpy((U8 *)&LineCoding, *ppbData, 7);
*piLen = 7;
DBG("dwDTERate=%u, bCharFormat=%u, bParityType=%u, bDataBits=%u\n",
LineCoding.dwDTERate,
LineCoding.bCharFormat,
LineCoding.bParityType,
LineCoding.bDataBits);
break;
// get line coding
case GET_LINE_CODING:
DBG("GET_LINE_CODING\n");
*ppbData = (U8 *)&LineCoding;
*piLen = 7;
break;
// set control line state
case SET_CONTROL_LINE_STATE:
// bit0 = DTR, bit = RTS
DBG("SET_CONTROL_LINE_STATE %X\n", pSetup->wValue);
break;
default:
return FALSE;
}
return TRUE;
}
/**
Initialises the VCOM port.
Call this function before using VCOM_putchar or VCOM_getchar
*/
void VCOM_init(void)
{
fifo_init(&txfifo, txdata);
fifo_init(&rxfifo, rxdata);
}
/**
Writes one character to VCOM port
@param [in] c character to write
@returns character written, or EOF if character could not be written
*/
int VCOM_putchar(int c)
{
return fifo_put(&txfifo, c) ? c : EOF;
}
/**
Reads one character from VCOM port
@returns character read, or EOF if character could not be read
*/
int VCOM_getchar(void)
{
U8 c;
return fifo_get(&rxfifo, &c) ? c : EOF;
}
/**
Interrupt handler
Simply calls the USB ISR, then signals end of interrupt to VIC
*/
static void USBIntHandler(void)
{
USBHwISR();
VICVectAddr = 0x00; // dummy write to VIC to signal end of ISR
}
static void USBFrameHandler(U16 wFrame)
{
if (fifo_avail(&txfifo) > 0) {
// data available, enable NAK interrupt on bulk in
USBHwNakIntEnable(INACK_BI);
}
}
int main(void) ////////////////////////MAIN/////////////////////
{
int c;
system_init();
pll_start(CRYSTAL, FREQUENCY);
//LED_DIR = 0xFF;
// LED pin - output
FIO0DIR|= 0xFF;
LcdInit();
LcdSendCmd(LCD_L1);
LcdTxt("ARM7");
//FIO1DIR = 0xFFFFFFFF;
//FIO1CLR = 0xFFFFFFFF;
// Uart0_init(115200, 8, 1);
// przerwanie_zew_init();
// timery_init();
//ConsoleInit(60000000 / (16 * BAUD_RATE));
DBG("Initialising USB stack\n");
LcdSendCmd(LCD_L1);
DBG("Init\n");
LcdTxt("Init");
// initialise stack
USBInit();
// register descriptors
USBRegisterDescriptors(abDescriptors);
// register class request handler
USBRegisterRequestHandler(REQTYPE_TYPE_CLASS, HandleClassRequest, abClassReqData);
// register endpoint handlers
USBHwRegisterEPIntHandler(INT_IN_EP, NULL);
USBHwRegisterEPIntHandler(BULK_IN_EP, BulkIn);
USBHwRegisterEPIntHandler(BULK_OUT_EP, BulkOut);
// register frame handler
USBHwRegisterFrameHandler(USBFrameHandler);
// enable bulk-in interrupts on NAKs
USBHwNakIntEnable(INACK_BI);
// initialise VCOM
VCOM_init();
////
LcdTxt("Strt");
// set up USB interrupt
VICIntSelect &= ~(1<<22); // select IRQ for USB
VICIntEnable |= (1<<22);
(*(&VICVectCntl0+INT_VECT_NUM)) = 0x20 | 22; // choose highest priority ISR slot
(*(&VICVectAddr0+INT_VECT_NUM)) = (int)USBIntHandler;
enable_irq();
// connect to bus
USBHwConnect(TRUE);
LcdTxt("4");
while (1)
{
c = VCOM_getchar();
if (c != -1) {
// show on console
if ((c == 9) || (c == 10) || (c == 13) || ((c >= 32) && (c <= 126))) {
//DBG("%c", c);
LcdN(c);
}
else {
//DBG(".");
LcdTxt(".");
}
VCOM_putchar(c);
LcdTxt("z");
}
//LcdTxt("5");
//PCON|=1;
// LcdSendCmd(LCD_L1+0);
// LcdN(T0TC);
//LcdSendCmd(LCD_L2+5);
//LcdN(counter);
//czekaj(9000000);
//FIO0SET=1<<5;
//czekaj(9000000);
//FIO0CLR=1<<5;
// change LED state
}
}
void przerwanie_zew_init(void)
{
//alternatywna funkcja dla p0.30 EINT3
PINSEL1&=(0x2)<<28;
PINSEL1|=(0x2)<<28;
//ustwienie wyzwalania
EXTMODE |=1<<3;
EXTPOLAR|=1<<3;
//kasuje wystapienie przerwania
EXTINT = 1<<3;
VICVectAddr0 = (unsigned int)Irq_Eint3;
// irq wlacz i przypisz kanal 17
VICVectCntl0 = (1<<5) | K_EINT3;
//kanał 17 enable
VICIntEnable = 1<<K_EINT3;
}
void timery_init(void)
{
//prescaler
T0PR = 60000 -1;
//zachowanie timera, zerowanie, resetowanie, przerwanie
T0MCR |= (1<<0) | (1<<3) | (1<<6) | (1<<9);
//Przerwanie 0 licznika 0
T0MR0 = 1000-1;
// T0MR1 = 5000-1;
// T0MR2 = 26700-1;
// T0MR3 = 30000-1;
// włacz timer
T0TCR = 1;
//obsluga przerwania
VICVectAddr1 = (unsigned int)Irq_Tim0;
// irq wlacz i przypisz kanał
VICVectCntl1 = (1<<5) | K_TIM0;
VICIntEnable = 1<<K_TIM0;
}
void Uart0_init(uint32_t bound, uint8_t bit, uint8_t stop)
{
uint16_t dzielnik;
// funkcje alternatywne dla P0.0 i P0.1
PINSEL0 |= (1) | (1<<2);
//Bit 8 pozwalający na zapisa dielników
U0LCR |= 1<<7;
dzielnik = FREQUENCY/bound/16;
U0DLL= (unsigned char)dzielnik;
U0DLM =(unsigned char) (dzielnik>>8);
//bity danych i bity stopu
U0LCR = ((bit-5)<<0) | ((stop-1)<<2);
//kolejka fifo
U0FCR = 1;
//Przerwania
VICVectAddr2 = (unsigned int)Irq_Uart0;
// irq wlacz i przypisz kanał
VICVectCntl2 = (1<<5) | K_UART0;
VICIntEnable = 1<<K_UART0;
U0IER=1;
}