// for LPC11U35 #ifndef _MRBC_API_H #define _MRBC_API_H #include "projectconfig.h" // GPIO #define MRBC_GPIO_IN 0x000 #define MRBC_GPIO_OUT 0x001 #define MRBC_GPIO_IN_PU 0x020 #define MRBC_GPIO_IN_PD 0x010 #define MRBC_GPIO_OUT_OD 0x801 #define MRBC_GPIO_IN_ANALOG 8 // pull down 2<<3 // pull up 2<<4 // open drain 2<<10 // pin numbers 0-31: P0.0-31, 32-63: P1.0-31 // PWM func (7:6) // ADC/no ADC (5), 32/16 timer(4), timer num (3) // GPIO func (2), PWM mat 0-3 (1:0) static volatile uint8_t pin_config[]={ 0004,0222,0,0, 0,0,0,0, 0200,0201,0306,0367, 0044,0374,0375,0376, 0273,0,0220,0221, 0,0110,0251,0040, 0,0,0,0, 0,0,0,0, 0130,0131,0132,0133, 0,0,0,0, 0,0,0,0, 0,0200,0201,0202, 0,0,0,0, 0,0,0,0111, 0120,0121,0122,0123, 0,0,0,0, }; // irregular GPIO func 1 : 0,10-15 pin_config[]&4 static inline void mrbcPinMode(uint8_t pin_id, uint32_t mode) { // 0_0-31, 1_0-31 uint8_t port_num = (pin_id >> 5) & 0x07; uint8_t pin_num = pin_id & 0x1F; if(port_num>1) return; LPC_SYSCON->SYSAHBCLKCTRL |= ((1<<6) | (1 << 16)); // GPIO and IOCON volatile uint32_t *temp_reg = (volatile uint32_t *)LPC_IOCON; temp_reg[pin_id-port_num*8] = (mode >>1) | ((pin_config[pin_id] & 4) >>2) ; //GPIOSetDir ( port_num, pin_num, mode&1 ); if(mode & 1){ LPC_GPIO->DIR[port_num] |= ( 1<DIR[port_num] &= ~( 1<> 5) & 0x07; uint8_t pin_num = pin_id & 0x1F; //GPIOSetBitValue ( port_num, pin_num, value ); if ( value ){ LPC_GPIO->SET[port_num] = 1<CLR[port_num] = 1<> 5) & 0x07; uint8_t pin_num = pin_id & 0x1F; //return GPIOGetPinValue ( port_num, pin_num ); return ( (LPC_GPIO->PIN[port_num] & (0x1<0 ); } // ADC #include "core/adc/adc.h" #define MRBC_ADC_RANGE 1023 //1023 #define MRBC_ADC_REF 3.3 //5.0 #define MRBC_ADC_TIMEOUT_MAX 100000 // ADC 11-16,22,23 pin_config[]&040 static inline uint8_t mrbcAnalogChannel(uint8_t pin_id) { uint8_t ch=0; uint8_t ret; for(int i=0;i<=pin_id;i++) if(pin_config[i] & 040){ret=ch++;}else{ret=0xff;} return ret; } // ADC func 1<<2 : 11-15, 1<<1 : 16,22,23 static inline uint8_t mrbcAnalogInit(uint8_t pin_id) { uint8_t ch = mrbcAnalogChannel(pin_id); if (ch == 0xff) return 0xff; mrbcPinMode(pin_id,2<<(ch<5)); adcInit(); return ch; } static inline uint16_t mrbcAnalogRead(uint8_t ch) { return adcRead(ch); } // PWM static inline void mrbcPwmWrite(uint8_t pin, uint32_t freq, uint16_t duty) { if(freq==0){ mrbcDigitalWrite(pin,0); mrbcPinMode(pin, MRBC_GPIO_OUT); return; } uint32_t limit=SystemCoreClock/freq; uint32_t prescaler=limit>>16; limit/=(prescaler+1); uint16_t val=limit*duty/10000; if(limit>0) limit--; if(pin>=sizeof(pin_config)) return; uint8_t fnc=pin_config[pin] & 0333; if(fnc == 0) return; uint8_t mat=fnc%4; uint8_t tmr=fnc/8%4; fnc>>=5; if(mat == 3) return; LPC_SYSCON->SYSAHBCLKCTRL |= (1 << (7+tmr)); LPC_CTxxBx_Type* tmr_reg = (LPC_CTxxBx_Type*) (LPC_CT16B0_BASE+0x4000*tmr); tmr_reg->PR=prescaler; tmr_reg->MR[3]=limit; tmr_reg->MCR = 1 << (3*3+1); // reset on MR3 if(mat != 3){ tmr_reg->MR[mat]=limit-val; tmr_reg->PWMC |= (1<EMR |= (3<<(mat*2+4)) | (1<TCR = 1; // enable timer mrbcPinMode(pin, fnc|1); } // I2C #define NO_I2C_HANDLE #define I2C_TIMEOUT_MAX 100000 #define I2C_WAIT_SI do{ \ uint32_t timeout = I2C_TIMEOUT_MAX; \ while (!(LPC_I2C->CONSET & 0x08)) { \ if (--timeout == 0) return -1; \ } \ } while(0) static inline void mrbcI2cInit(void* handle, uint32_t freq, int scl, int sda) { LPC_SYSCON->PRESETCTRL |= (0x1<<1); LPC_SYSCON->SYSAHBCLKCTRL |= (1<<5); // I2C mrbcPinMode(4,3); // P0.4(SCL) mrbcPinMode(5,2); // P0.5(SDA) LPC_I2C->CONCLR = 4 | 8 | 0x20 | 0x40; // ack, SI, start, enable if(freq>800000){ // fast mode plus LPC_IOCON->PIO0_4 |= (0x200); LPC_IOCON->PIO0_5 |= (0x200); } LPC_I2C->SCLL = SystemCoreClock / freq / 2; LPC_I2C->SCLH = SystemCoreClock / freq / 2; LPC_I2C->CONSET = 0x40; // I2C enable as master mode } static inline int mrbcI2cStop(void* handle) { LPC_I2C->CONSET = 0x10; // stop flag LPC_I2C->CONCLR = 0x08; // SI flag uint32_t timeout = I2C_TIMEOUT_MAX; while (LPC_I2C->CONSET & 0x10){ if (--timeout == 0){LPC_I2C->CONCLR = 0x10; return -1;} } return 0; } static inline int mrbcI2cStart(void* handle, uint8_t adrs, uint8_t rw) // rw=1 if read { //if(LPC_I2C->STAT == 0x28) {// repeated //if(rw) {// repeated if(LPC_I2C->CONSET & 0x08) {// repeated LPC_I2C->CONSET = 0x20; // start flag LPC_I2C->CONCLR = 0x08; // !si }else{ LPC_I2C->CONSET = 0x20; // start flag } uint32_t timeout = I2C_TIMEOUT_MAX; while (!(LPC_I2C->CONSET & 0x08)) { if (--timeout == 0) return -1; } if ( LPC_I2C->STAT != 0x08 && LPC_I2C->STAT != 0x10 ) return -1; LPC_I2C->DAT = (adrs << 1) | (rw>0) ; LPC_I2C->CONCLR = 0x08 | 0x20; // !si !start I2C_WAIT_SI; if ( LPC_I2C->STAT == 0x18 || LPC_I2C->STAT == 0x40 ) return 0; mrbcI2cStop(NULL); return -1; } static inline int mrbcI2cWrite(void* handle, const uint8_t *buf, uint16_t len) { for (uint16_t i = 0; i < len; i++) { LPC_I2C->DAT = buf[i]; LPC_I2C->CONCLR = 0x08; // !si I2C_WAIT_SI; if (LPC_I2C->STAT != 0x28) return -1; } return 0; } static inline int mrbcI2cRead(void* handle, uint8_t *buf, uint16_t len) { uint16_t i; for (i = 0; i < len; i++) { if (i == (len - 1)) { LPC_I2C->CONCLR = 0x04; // NACK } else { LPC_I2C->CONSET = 0x04; // ACK } LPC_I2C->CONCLR = 0x08; // SI uint32_t timeout = I2C_TIMEOUT_MAX; while (!(LPC_I2C->CONSET & 0x08)) { if (--timeout == 0) break; } if ( LPC_I2C->STAT != 0x50 && LPC_I2C->STAT != 0x58 ) break; buf[i] = LPC_I2C->DAT; } mrbcI2cStop(NULL); return i; } // SPI #define MRBC_SPI_LSB_FIRST 1 #define MRBC_SPI_MSB_FIRST 0 typedef struct SPI_HANDLE { uint8_t unit_num; LPC_SSPx_Type* ssp; uint8_t first_bit; } SPI_HANDLE; //#define NO_SPI_HANDLE static inline uint8_t mrbc_rev_bit8(uint8_t x) { x = ((x & 0xAA) >> 1) | ((x & 0x55) << 1); x = ((x & 0xCC) >> 2) | ((x & 0x33) << 2); x = ((x & 0xF0) >> 4) | ((x & 0x0F) << 4); return x; } #define SPI_TIMEOUT_MAX 100000 //LPC_SSPx_Type* spi_base[] = {LPC_SSP0, LPC_SSP1}; //#define LPC_SSP0_BASE (0x40040000) //#define LPC_SSP1_BASE (0x40058000) static inline void mrbcSpiInit(SPI_HANDLE *handle) { uint8_t unit=(handle->unit_num > 0); //LPC_SSPx_Type* ssp = spi_base[unit]; LPC_SSPx_Type* ssp = (LPC_SSPx_Type*)(((uint8_t *) LPC_SSP0)+0x18000*unit); handle->ssp = ssp; LPC_SYSCON->PRESETCTRL |= 0x01; if(unit==0){ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11); // SPI0 mrbcPinMode(8,2); // MISO in mrbcPinMode(9,3); // MOSI out mrbcPinMode(10,5); // SCK out }else{ LPC_SYSCON->SYSAHBCLKCTRL |= (1<<18); // SPI1 mrbcPinMode(22,6); // MISO in mrbcPinMode(21,5); // MOSI out mrbcPinMode(47,7); // SCK out P1.15 } for (uint8_t i = 8; i--; ) (void)ssp->DR; ssp->CR1 = 2; // enable, master, no loopback } static inline void mrbcSpiMode(SPI_HANDLE *handle, uint32_t spi_freq, uint32_t spi_first_bit, uint32_t spi_mode) { LPC_SSPx_Type* ssp = handle->ssp; // spi_freq=SystemCoreClock/ClockDiv/CPSR/(PCR+1); uint32_t clkdiv = 1; uint32_t cpsdvsr = 1; uint32_t scr = 0; uint32_t totalDiv = SystemCoreClock / spi_freq; if (totalDiv < 2) totalDiv = 2; if (totalDiv > 65024) { clkdiv = (totalDiv + 65023) / 65024; if (clkdiv > 255) clkdiv = 255; totalDiv = SystemCoreClock / spi_freq / clkdiv; } totalDiv/=2; cpsdvsr = (totalDiv + 255) / 256; if (cpsdvsr == 0) cpsdvsr = 1; if (cpsdvsr > 127) cpsdvsr = 127; scr = (totalDiv + (cpsdvsr / 2)) / cpsdvsr; if (scr > 256) scr = 256; if (scr == 0) scr = 1; if(handle->unit_num==0){ LPC_SYSCON->SSP0CLKDIV = clkdiv; }else{ LPC_SYSCON->SSP1CLKDIV = clkdiv; } ssp->CPSR = cpsdvsr*2; // clock prescale ssp->CR0 = ( (7 << 0) // Data size = 8-bit | (0 << 4) // Frame format = SPI | ((spi_mode & 3) <<6) | ((scr-1) <<8) ); // Clock rate handle->first_bit=spi_first_bit; } static inline void mrbcSpiTransfer(SPI_HANDLE *handle, uint8_t *buf, uint32_t len) { LPC_SSPx_Type* ssp = handle->ssp; uint32_t timeout = SPI_TIMEOUT_MAX; uint32_t tx_i = 0; uint32_t rx_i = 0; while ((tx_i < len) || (rx_i < len)) { if ((tx_i < len) && (ssp->SR & 2)) { // Tx not full ssp->DR = (handle->first_bit)? mrbc_rev_bit8(buf[tx_i]) : buf[tx_i]; tx_i++; timeout = SPI_TIMEOUT_MAX; } if ((rx_i < len) && (ssp->SR & 4)) { // Rx not empty buf[rx_i++] = (handle->first_bit)? mrbc_rev_bit8(ssp->DR) : ssp->DR; timeout = SPI_TIMEOUT_MAX; } if (--timeout == 0) return; } } // UART #define MRBC_UART_NONE 0 #define MRBC_UART_EVEN 0x18 #define MRBC_UART_ODD 0x08 //typedef struct UART_HANDLE { // uint8_t unit_num; //} UART_HANDLE; #define NO_UART_HANDLE #define UART_TIMEOUT_MAX 100000 static inline void mrbcUartInit(void *handle) { //int unit_num = handle->unit_num; LPC_SYSCON->SYSAHBCLKCTRL |= (1<<12); // UART LPC_SYSCON->UARTCLKDIV = 1; mrbcPinMode(18,2); // rx in mrbcPinMode(19,3); // tx out LPC_USART->IER = 0; //no interrupt LPC_USART->FCR = 7; // Enable and reset TX and RX FIFO. } static inline void mrbcUartSetMode(void *handle, uint32_t baud_rate, uint32_t datb, uint32_t stpb, uint32_t prty ) { LPC_USART->LCR = ( 3 | // 8bit ((stpb-1)&1)<<2 | prty | 0 | // break tx disable 0x80 ); //DLAB=1 uint32_t fDiv = ((SystemCoreClock/LPC_SYSCON->UARTCLKDIV)/16)/baud_rate; LPC_USART->DLM = fDiv / 256; LPC_USART->DLL = fDiv % 256; LPC_USART->LCR = ( 3 | // 8bit ((stpb-1)&1)<<2 | prty | 0 | // break tx disable 0 ); //DLAB=0 } static inline int mrbcUartByteToWrite(void *handle) { return !(LPC_USART->LSR & (1<<6)); } static inline int mrbcUartWrite(void *handle, const char *buf, int size){ for(int i = 0; i < size; i++){ uint32_t timeout = UART_TIMEOUT_MAX; while ( !(LPC_USART->LSR & (1<<5) ) ) //THRE { if (--timeout == 0) return -1;} LPC_USART->THR = buf[i]; } return size; } static inline int mrbcUartAvailable(void *handle){ return (LPC_USART->LSR & 1); } static inline int mrbcUartRead(void *handle, char *buf, int size){ for(int i = 0; i < size ; ){ if( LPC_USART->LSR & 1 ) buf[i++] = LPC_USART->RBR; } buf[size] = '\0'; return size; } static inline int mrbcUartCanReadLine(void *handle){ return 0; } static inline void mrbcUartFlush(void *handle) { } static inline void mrbcUartClearRx(void *handle) { LPC_USART->FCR = 3; // Enable and reset RX FIFO. } static inline void mrbcUartClearTx(void *handle) { LPC_USART->FCR = 5; // Enable and reset TX FIFO. } // DAC // SLEEP extern volatile uint32_t delayTicks; static inline void mrbcSleepLight(uint32_t ms){ // ms uint32_t curTicks = delayTicks; while ((delayTicks - curTicks) < ms) { SCB->SCR &= ~(SCB_SCR_SLEEPDEEP_Msk); __WFI(); } } static inline void mrbcSleepDeep(uint32_t val){ // ms, 2h max LPC_SYSCON->PDRUNCFG &= ~(1 << 6); LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 15); LPC_SYSCON->WDTOSCCTRL = (0x01 << 5) | 0x1F; // 2344Hz LPC_WWDT->TC = val*2344/1000; if (val > 0xFFFFFF) val = 0xFFFFFF; if (val < 0xFF) val = 0xFF; LPC_WWDT->MOD = 0x03; //reset LPC_WWDT->FEED = 0xAA; LPC_WWDT->FEED = 0x55; LPC_SYSCON->STARTERP1 |= (1 << 12); LPC_SYSCON->PDAWAKECFG = LPC_SYSCON->PDRUNCFG; LPC_PMU->PCON = (LPC_PMU->PCON & ~0x7) | 0x1; SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; __WFI(); while(1); } #endif