Last active
August 29, 2015 13:57
-
-
Save Aflecht/9380101 to your computer and use it in GitHub Desktop.
MIDI I/O with NXP LPC43xx micro controller (ARM Cortex M4 MCU)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define CMSIS_BITPOSITIONS | |
#include <__cross_studio_io.h> | |
#include "lpc43xx.h" | |
// | |
// Configure LPC43xx ARM Cortex M4 microcontroller to 204 MHz using 12 MHz crystal | |
// | |
void Configure_Main_Clock_And_Busses() | |
{ | |
// Enable crystal oscillator | |
LPC_CGU->XTAL_OSC_CTRL = 0; | |
for (volatile uint32_t i = 0; i < 1000000; ++i); | |
// Set the PLL to 204 MHz | |
uint32_t control_register = LPC_CGU->PLL1_CTRL; | |
control_register &= ~(CGU_PLL1_CTRL_MSEL_Msk | CGU_PLL1_CTRL_CLK_SEL_Msk | CGU_PLL1_CTRL_PD_Msk); | |
control_register |= 16 << CGU_PLL1_CTRL_MSEL_Pos; // Feedback-divider division ratio = 17 ---> 17 * 12 MHz = 204 MHz | |
control_register |= 6 << CGU_PLL1_CTRL_CLK_SEL_Pos; // Clock source = crystal oscillator | |
LPC_CGU->PLL1_CTRL = control_register; | |
while (!(LPC_CGU->PLL1_STAT & CGU_PLL1_STAT_LOCK_Msk)); | |
// Set M4 clock to PLL1 | |
LPC_CGU->BASE_M4_CLK = 9 << CGU_BASE_M4_CLK_CLK_SEL_Pos | // Clock source = PLL1 | |
1 << CGU_BASE_M4_CLK_AUTOBLOCK_Pos; // Block clock automatically during frequency change | |
// Set PERIPH clock to PLL1 | |
LPC_CGU->BASE_PERIPH_CLK = 9 << CGU_BASE_PERIPH_CLK_CLK_SEL_Pos | // Clock source = PLL1 | |
1 << CGU_BASE_PERIPH_CLK_AUTOBLOCK_Pos; // Block clock automatically during frequency change | |
// Set APB1 clock to PLL1 | |
LPC_CGU->BASE_APB1_CLK = 9 << CGU_BASE_APB1_CLK_CLK_SEL_Pos | // Clock source = PLL1 | |
1 << CGU_BASE_APB1_CLK_AUTOBLOCK_Pos; // Block clock automatically during frequency change | |
// Set APB3 clock to PLL1 | |
LPC_CGU->BASE_APB3_CLK = 9 << CGU_BASE_APB3_CLK_CLK_SEL_Pos | // Clock source = PLL1 | |
1 << CGU_BASE_APB3_CLK_AUTOBLOCK_Pos; // Block clock automatically during frequency change | |
} | |
/* | |
Use UART1 input & output for MIDI. | |
Pin P1_13 = MIDI output | |
Pin P1_14 = MIDI input | |
------------ | |
Crystal = 12 MHz | |
MIDI baud rate = 31250 | |
12 MHz / 31250 = 384 cycles per baud | |
UART is always 16x oversampling. | |
*/ | |
void Configure_MIDI_IO() | |
{ | |
// Set UART1 clock to crystal | |
LPC_CGU->BASE_UART1_CLK |= 6 << CGU_BASE_UART1_CLK_CLK_SEL_Pos | // UART1 clock source = Crystal | |
1 << CGU_BASE_UART1_CLK_AUTOBLOCK_Pos; // Block clock automatically during frequency change | |
// MIDI format = 31250 baud, 1 start bit, 8 data, no parity, 1 stop bit | |
LPC_UART1->LCR |= 3 << UART1_LCR_WLS_Pos | // 8bit character length | |
UART1_LCR_DLAB_Msk; // Enable Divisor Latch Access | |
LPC_UART1->DLL &= ~UART1_DLL_DLLSB_Msk; | |
LPC_UART1->DLL |= 24 << UART1_DLL_DLLSB_Pos; // 12MHz clock, 31250 baud, 16x oversampling ---> 12MHz / (16 * 31250) = 24 | |
LPC_UART1->LCR &= ~UART1_LCR_DLAB_Msk; // Disable Divisor Latch Access | |
LPC_UART1->FCR |= UART1_FCR_FIFOEN_Msk; // Enable FIFO | |
// Set pin functionalities | |
LPC_SCU->SFSP1_13 |= 1 << SCU_SFSP1_13_MODE_Pos; // P1_13 = FUNC1 = UART1 TXD = MIDI-OUT-1 | |
LPC_SCU->SFSP1_14 |= 1 << SCU_SFSP1_14_MODE_Pos; // P1_14 = FUNC1 = UART1 RXD = MIDI-IN-1 | |
LPC_SCU->SFSP1_14 |= SCU_SFSP1_14_EZI_Msk; // P1_14 = Enable input buffer | |
} | |
void Send_MIDI_Message(uint32_t message_24bit) | |
{ | |
while (!(LPC_UART1->LSR & UART1_LSR_THRE_Msk)); // Wait until UART1 THR is empty | |
LPC_UART1->THR = (message_24bit >> 16) & 0xFF; | |
while (!(LPC_UART1->LSR & UART1_LSR_THRE_Msk)); | |
LPC_UART1->THR = (message_24bit >> 8) & 0xFF; | |
while (!(LPC_UART1->LSR & UART1_LSR_THRE_Msk)); | |
LPC_UART1->THR = message_24bit & 0xFF; | |
} | |
void main(void) | |
{ | |
Configure_Main_Clock_And_Busses(); | |
Configure_MIDI_IO(); | |
// MIDI input test | |
while (1) | |
{ | |
if (LPC_UART1->LSR & UART1_LSR_RDR_Msk) | |
debug_printf("%x ", LPC_UART1->RBR & 0xFF); | |
} | |
/* | |
// MIDI output test | |
while (1) | |
{ | |
Send_MIDI_Message(0x0090017F); // Note on | |
for (volatile uint32_t i = 0; i < 4000000; ++i); | |
Send_MIDI_Message(0x00900100); // Note off | |
for (volatile uint32_t i = 0; i < 8000000; ++i); | |
} | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This example uses NXP LPC4330FBD144 microcontroller.
It's should be usable with other LPC43xx microcontrollers with minimal changes.