#include <xc.h>
#include <stdint.h>
#define STRING_LENGTH 64
#define VERSION "0.1"
#define POWER_ON_LED PORTCbits.RC3
#define LED1 PORTBbits.RB2
#define USB_CONNECTED PORTCbits.RC1
#define LED4 PORTCbits.RC0
#define UART_TXQueue_SIZE 256
_CONFIG1(JTAGEN_OFF & GCP_OFF & GWRP_OFF & FWDTEN_OFF & WINDIS_OFF & ICS_PGx3)
_CONFIG2(IESO_OFF & POSCMOD_NONE & OSCIOFNC_ON & FCKSM_CSDCMD & FNOSC_FRCPLL & PLL96MHZ_ON & PLLDIV_DIV2)
_CONFIG3(WPFP_WPFP0 & SOSCSEL_IO & WUTSEL_FST & WPDIS_WPDIS & WPCFG_WPCFGDIS & WPEND_WPENDMEM)
_CONFIG4(DSWDTPS_DSWDTPS3 & DSWDTOSC_LPRC & RTCOSC_LPRC & DSBOREN_OFF & DSWDTEN_OFF)
volatile uint16_t UARTTXQueueTail, UARTTXQueueHead, UARTTXQueueLength, USBEnumerationProcess;
volatile char UARTTXQueue[UART_TXQueue_SIZE];
void string2UARTTXQueue(char str[]);
char popUARTTXQueue();
void pushUARTTXQueue(char UARTVal);
//*** UART1 Receive interrupt function ***
//**************************************** k
void __attribute__((__interrupt__, __auto_psv__)) _U1RXInterrupt(void) {
IFS0bits.U1RXIF = 0; //Reset UART1 Receive interrupt bit
U1TXREG = U1RXREG; //Transmit received character
return;
}
//*** USB1 interrupt function ***
//****************************************
void __attribute__((__interrupt__, __auto_psv__)) _USB1Interrupt(void) {
extern volatile uint16_t USBEnumerationProcess;
if (U1IRbits.ATTACHIF == 1 && U1IEbits.ATTACHIE == 1) {
string2UARTTXQueue("USB device attached.\r\n");
USBEnumerationProcess = 1;
U1IR = 0x41;
U1IE = 0x01;
PORTCbits.RC1 = 1; //Light an LED
} else if (U1IRbits.DETACHIF == 1 && U1IEbits.DETACHIE == 1) {
string2UARTTXQueue("USB device detached.\r\n");
USBEnumerationProcess = 0;
U1IR = 0x41;
U1IE = 0x40;
U1ADDRbits.LSPDEN = 0; //The low speed registers need to be reset here
U1EP0bits.LSPD = 0; //or the device will be misidentified at the next attachement
PORTCbits.RC1 = 0; //Unlight an LED
}
IFS5bits.USB1IF = 0; //Clear
return;
}
int16_t main() {
extern volatile uint16_t UARTTXQueueTail, UARTTXQueueHead, UARTTXQueueLength, USBEnumerationProcess;
UARTTXQueueTail = 0;
UARTTXQueueHead = 0;
UARTTXQueueLength = 0;
USBEnumerationProcess = 0;
TRISB = 0x00;
TRISC = 0x00;
PORTC = 0x08;
uint16_t pll_startup_counter = 600;
CLKDIVbits.PLLEN = 1;
while (pll_startup_counter--);
PORTC = 0x09; //Turn on LED when PLL is locked
U1PWRCbits.USBPWR = 1;
CLKDIVbits.CPDIV = 0b10;
TRISA = 0x02; //RA1 as input
AD1PCFG = 0xffff; //No analogue inputs
IFS0 = 0x0000; //Interrupts reset
IEC0 = 0x0800; //Uart recieve interrupt enabled
POWER_ON_LED = 1;
//Reconfigurable pin setup
__builtin_write_OSCCONL(OSCCON & 0xBF);
RPOR2bits.RP5R = 3; //RP5 as UART1 TX
RPINR18bits.U1RXR = 0x06; //RP6 as UART1 RX
__builtin_write_OSCCONL(OSCCON | 0x40);
U1BRG = 8; //Baud rate set to 56k, U1BRG = (8MHz/2)/(4*56000) - 1
U1MODE = 0x8808; //UART1 enabled in simplex mode
U1STA = 0x8400; //Interrupt when char is transferred to TSR and Transmit enabled
U1MODEbits.BRGH = 1;
//USB1 host mode setup
U1CONbits.HOSTEN = 1;
U1OTGCONbits.DPPULDWN = 1;
U1OTGCONbits.DMPULDWN = 1;
U1OTGCONbits.DPPULUP = 0;
U1OTGCONbits.DMPULUP = 0;
U1IRbits.ATTACHIF = 0;
U1IEbits.ATTACHIE = 1;
IEC5bits.USB1IE = 1;
char build_date[] = __DATE__;
string2UARTTXQueue("***************************");
string2UARTTXQueue("\r\n\r\n");
string2UARTTXQueue("Welcome to MIDI2VC+\r\nVersion ");
string2UARTTXQueue(VERSION);
string2UARTTXQueue("\r\n");
string2UARTTXQueue("Build date ");
string2UARTTXQueue(build_date);
string2UARTTXQueue("\r\n\r\n");
string2UARTTXQueue("***************************\r\n");
while (1) {
switch (USBEnumerationProcess) {
case 0:
break;
case 1:
if (U1CONbits.JSTATE == 0) {
string2UARTTXQueue("Low speed device found\r\n");
U1ADDRbits.LSPDEN = 1;
U1EP0bits.LSPD = 1;
USBEnumerationProcess = 2;
} else {
string2UARTTXQueue("Full speed device found\r\n");
U1ADDRbits.LSPDEN = 0;
U1EP0bits.LSPD = 0;
USBEnumerationProcess = 2;
}
break;
default:
break;
}
if (UARTTXQueueLength > 0 && U1STAbits.UTXBF == 0) {
U1TXREG = popUARTTXQueue();
}
}
return 0;
}
//*********************************************************
//*******Function string2UARTTXQueue**********************
//Takes a c-string and sends it to the UART transmit Queue
void string2UARTTXQueue(char str[]) {
uint16_t i = 0;
while (str[i] != 0) {
pushUARTTXQueue(str[i]);
i++;
}
return;
}
//*********************************************************
//*******Function popUARTTXQueue**********************
//Returns next value in UART transmit Queue and
//sets queue values apropriately
char popUARTTXQueue() {
char UARTVal;
extern volatile uint16_t UARTTXQueueTail, UARTTXQueueHead, UARTTXQueueLength;
extern volatile char UARTTXQueue[UART_TXQueue_SIZE];
if (UARTTXQueueLength == 0) {
return 0;
}
UARTTXQueueTail = (UARTTXQueueTail + 1) & (UART_TXQueue_SIZE - 1);
UARTVal = UARTTXQueue[UARTTXQueueTail];
UARTTXQueueLength--;
return UARTVal;
}
//*********************************************************
//*******Function popUARTTXQueue**********************
//Puts a char to the UART transmit Queue and
//sets queue values apropriately
void pushUARTTXQueue(char UARTVal) {
extern volatile uint16_t UARTTXQueueTail, UARTTXQueueHead, UARTTXQueueLength;
extern volatile char UARTTXQueue[UART_TXQueue_SIZE];
if (UARTTXQueueLength == (UART_TXQueue_SIZE - 1)) {
return;
}
UARTTXQueueHead = (UARTTXQueueHead + 1) & (UART_TXQueue_SIZE - 1);
UARTTXQueue[UARTTXQueueHead] = UARTVal;
UARTTXQueueLength++;
return;
}
Tuesday, October 14, 2014
MIDI2VC+, USB device detection
Work on the MIDI2VC+ is slow but steady. The USB protocol is pretty complicated, especially for a host. But I'm taking it one step at a time. The implementation of a UART with functions for outputting strings, makes the whole thing more manageable. I've gotten so far as to identifying an attached device as "Full Speed" or "Low Speed" and managing the detaching. Here's the code for the project so far:
Wednesday, October 8, 2014
SA0***
I finally got my amateur radio license, which feels nice. The test was quite hard. Today I got a call from the license issuer, who asked what I call sign I wanted. Apparently I'm the first in the region who got to choose my own call sign, as long as it wasn't taken previously.
Subscribe to:
Posts (Atom)