Created
February 8, 2014 21:41
-
-
Save 46bit/8890761 to your computer and use it in GitHub Desktop.
Library to make using LPC17xx easier. Not freely licensed, may not be mine to give away. Here for https://gist.github.com/46bit/8890681
This file contains hidden or 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
#include "lpc17xx_i2c.h" | |
#include "lpc17xx_pinsel.h" | |
#include "lpc17xx_uart.h" | |
#include "lpc17xx_gpio.h" | |
#include "lpc17xx_nvic.h" | |
#include "lpc17xx_gpdma.h" | |
#include "lpc17xx_adc.h" | |
#include "lpc17xx_dac.h" | |
#include <math.h> | |
#include <string.h> | |
#define I2CDEV_M LPC_I2C1 | |
#define I2CDEV_S_ADDR 0x21 | |
#define BUFFER_SIZE 0x40 | |
#define ASCII_OFFSET 0x80 | |
#define MCB_LPC_1768 | |
//#define IAR_LPC_1768 | |
#ifdef MCB_LPC_1768 | |
#define _ADC_INT ADC_ADINTEN2 | |
#define _ADC_CHANNEL ADC_CHANNEL_2 | |
#elif defined(IAR_LPC_1768) | |
#define _ADC_INT ADC_ADINTEN5 | |
#define _ADC_CHANNEL ADC_CHANNEL_5 | |
#endif | |
#define DMA_SIZE 1 | |
const char ch[4][4] = { | |
{'1', '2', '3', 'A'}, | |
{'4', '5', '6', 'B'}, | |
{'7', '8', '9', 'C'}, | |
{'*', '0', '#', 'D'} | |
}; | |
const unsigned long led_mask[] = { 1<<18, 1<<20, 1<<21, 1<<23 }; | |
int led_init_run = 0; | |
int led_value = 0; | |
void tty_init(void); | |
void led_init(void); | |
void i2c_init(void); | |
void led_init(void) { | |
led_init_run = 1; | |
int l; | |
for (l = 0; l < 4; l++) { | |
GPIO_SetDir(1, led_mask[l], 1); | |
GPIO_ClearValue(1, led_mask[l]); | |
} | |
} | |
void led_write_binary(int n) { | |
if (led_init_run == 0) return; | |
int k = 0; | |
for(k = 0; k < 4; k++) { | |
GPIO_ClearValue(1, led_mask[k]); | |
if ((n & ( 1 << k)) >> k == 1) { | |
GPIO_SetValue(1, led_mask[k]); | |
} | |
} | |
} | |
void tty_init(void) { | |
UART_CFG_Type UARTConfigStruct; | |
UART_FIFO_CFG_Type UARTFIFOConfigStruct; | |
PINSEL_CFG_Type PinCfg; | |
PinCfg.Funcnum = 1; | |
PinCfg.OpenDrain = 0; | |
PinCfg.Pinmode = 0; | |
PinCfg.Portnum = 0; | |
PinCfg.Pinnum = 2; | |
PINSEL_ConfigPin(&PinCfg); | |
PinCfg.Pinnum = 3; | |
PINSEL_ConfigPin(&PinCfg); | |
UART_ConfigStructInit(&UARTConfigStruct); | |
UART_FIFOConfigStructInit(&UARTFIFOConfigStruct); | |
UART_Init((LPC_UART_TypeDef *)LPC_UART0, &UARTConfigStruct); | |
UART_FIFOConfig((LPC_UART_TypeDef *)LPC_UART0, &UARTFIFOConfigStruct); | |
UART_TxCmd((LPC_UART_TypeDef *)LPC_UART0, ENABLE); | |
} | |
void i2c_init(void) { | |
PINSEL_CFG_Type PinCfg; | |
PinCfg.OpenDrain = 0; | |
PinCfg.Pinmode = 0; | |
PinCfg.Funcnum = 3; | |
PinCfg.Pinnum = 0; | |
PinCfg.Portnum = 0; | |
PINSEL_ConfigPin(&PinCfg); | |
PinCfg.Pinnum = 1; | |
PINSEL_ConfigPin(&PinCfg); | |
I2C_Init(I2CDEV_M, 100000); | |
I2C_Cmd(I2CDEV_M, ENABLE); | |
} | |
int lcd_init(void) { | |
i2c_init(); | |
uint8_t buf[12]; | |
buf[0] = 0x00; // Control byte for Instruction | |
buf[1] = 0x34; // DL: 8 bits, M: 16 by two line display, SL: 1:18, H: normal instruction set | |
buf[2] = 0x0E; // D: Display on, C: curser off, B: blink off | |
buf[3] = 0x06; // I/D: increment, S: no shift | |
buf[4] = 0x35; // DL: 8 bits, M: 16 by two line, SL: 1:18, H: extended instruction set | |
buf[5] = 0x04; // P: left to right, Q: top to bottom | |
buf[6] = 0x10; // TC1: 0, TC2: 0 | |
buf[7] = 0x42; // HV Stages 3 | |
buf[8] = 0x9f; // set Vlcd, store to VA | |
buf[9] = 0x34; // DL: 8 bits, M: two line, SL: 1:18, H: normal instruction set | |
buf[10] = 0x80; // DDRAM Address set to 00hex | |
buf[11] = 0x02; // return home | |
I2C_M_SETUP_Type transferMCfg; | |
transferMCfg.tx_data = buf; | |
transferMCfg.tx_length = sizeof(buf); | |
transferMCfg.rx_data = NULL; | |
transferMCfg.rx_length = 0; | |
transferMCfg.retransmissions_max = 3; | |
transferMCfg.sl_addr7bit = 0x3b; | |
int success = I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING); | |
return success; | |
} | |
int write_usb_serial_blocking(char *buf,int length){ | |
return(UART_Send((LPC_UART_TypeDef *)LPC_UART0,(uint8_t *)buf,length, BLOCKING)); | |
} | |
void tty_write(char *buf){ | |
led_write_binary(++led_value); | |
int length = 0; | |
uint8_t chr = buf[0]; | |
while(chr != '\0'){ | |
length++; | |
chr = buf[length]; | |
} | |
write_usb_serial_blocking(buf, length); | |
} | |
void tty_writeln(char *buf){ | |
tty_write(buf); | |
write_usb_serial_blocking("\n\r", 2); | |
} | |
void tty_write_binary(uint32_t n) { | |
int k = 0; | |
char chars[13]; | |
chars[0] = '0'; | |
chars[1] = 'b'; | |
chars[12] = 0; | |
for(k = 0; k < 32; k++) { | |
if ((n & ( 1 << k)) >> k == 1) { | |
chars[11-k] = '1'; | |
} else { | |
chars[11-k] = '0'; | |
} | |
} | |
tty_writeln(chars); | |
} | |
void tty_write_int(int n) { | |
char chars[30]; | |
int i; | |
for (i = 0; i < 29; i++) { | |
chars[i] = ' '; | |
} | |
chars[29] = 0; | |
i = 0; | |
while (n > 0 || i == 0) { | |
i++; | |
chars[29 - i] = (n % 10) + '0'; | |
n = n / 10; | |
} | |
tty_writeln(chars); | |
} | |
// @TODO: Only supports floats from 0 to 1. | |
void tty_write_float (float percent) { | |
char digits[17]; | |
int digiti; | |
for (digiti = 0; digiti < 16; digiti++) { | |
digits[digiti] = '0'; | |
} | |
digits[16] = 0; | |
int k = 2; | |
if (percent > 1) { | |
for (digiti = 0; digiti < 16; digiti++) { | |
digits[digiti] = '?'; | |
} | |
} else if (percent == 1) { | |
digits[0] = '1'; | |
digits[1] = '.'; | |
} else { | |
digits[0] = '0'; | |
digits[1] = '.'; | |
float t = percent; | |
while (t > 0 && k <= 13) { | |
t = t * 10; | |
int ti = (int) t; | |
t -= ti; | |
digits[k] = ti + '0'; | |
k++; | |
} | |
} | |
tty_writeln(digits); | |
} | |
char ascii_to_lcd(char ch) | |
{ | |
// c = 0xA0; // default: white space (nbsp) | |
char c; | |
if(ch < 30 || ch > 127){ | |
c = 0xA0; | |
} | |
else{ | |
c = ASCII_OFFSET + ch; | |
} | |
return c; | |
} | |
int read_keyboard_once(int mask_code) { | |
uint8_t write_buffer[1], read_buffer[1]; | |
write_buffer[0] = mask_code; | |
I2C_M_SETUP_Type transferMCfg; | |
transferMCfg.tx_data = write_buffer; | |
transferMCfg.tx_length = sizeof(write_buffer); | |
transferMCfg.rx_data = read_buffer; | |
transferMCfg.rx_length = sizeof(read_buffer); | |
transferMCfg.retransmissions_max = 3; | |
transferMCfg.sl_addr7bit = 0x21; | |
int success; | |
success = I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING); | |
if (success == 1) { | |
return read_buffer[0]; | |
} else { | |
return -1; | |
} | |
} | |
char read_keyboard(void){ | |
int keymasks[4]; | |
keymasks[0] = read_keyboard_once(0b01111111); | |
keymasks[1] = read_keyboard_once(0b10111111); | |
keymasks[2] = read_keyboard_once(0b11011111); | |
keymasks[3] = read_keyboard_once(0b11101111); | |
int i, j; | |
for (i = 0; i < 4; i++) { | |
for (j = 0; j < 4; j++) { | |
if ((keymasks[i] & 1<<j) >> j == 0) { | |
return ch[3 - j][i]; | |
} | |
} | |
} | |
return ' '; | |
} | |
int lcd_raw_read (uint8_t *lcd_write_buffer, int lcd_write_buffer_size, uint8_t *lcd_read_buffer, int lcd_read_buffer_size) { | |
I2C_M_SETUP_Type transferMCfg; | |
transferMCfg.tx_data = lcd_write_buffer; | |
transferMCfg.tx_length = lcd_write_buffer_size; | |
transferMCfg.rx_data = lcd_read_buffer; | |
transferMCfg.rx_length = lcd_read_buffer_size; | |
transferMCfg.retransmissions_max = 3; | |
transferMCfg.sl_addr7bit =0x3b; | |
int success; | |
success = I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING); | |
return (success == 1); | |
} | |
int lcd_raw_write(uint8_t *lcd_buffer, int lcd_buffer_size){ | |
if (!lcd_init()) { | |
led_write_binary(8); | |
return 0; | |
} | |
I2C_M_SETUP_Type transferMCfg; | |
transferMCfg.tx_data = lcd_buffer; | |
transferMCfg.tx_length = lcd_buffer_size; | |
transferMCfg.rx_data = NULL; | |
transferMCfg.rx_length = 0; | |
transferMCfg.retransmissions_max = 3; | |
transferMCfg.sl_addr7bit = 0x3b; | |
int success; | |
success = I2C_MasterTransferData(I2CDEV_M, &transferMCfg, I2C_TRANSFER_POLLING); | |
return (success == 1); | |
} | |
int lcd_busy(void) { | |
uint8_t busy_lcd_write_buffer[2], busy_lcd_read_buffer[2]; | |
busy_lcd_write_buffer[0] = 0; | |
lcd_raw_read(&busy_lcd_write_buffer[0], sizeof(busy_lcd_write_buffer), &busy_lcd_read_buffer[0], sizeof(busy_lcd_read_buffer)); | |
return busy_lcd_read_buffer[0] >> 7; | |
} | |
void lcd_clear(void) { | |
uint8_t clear_lcd_buffer[2]; | |
clear_lcd_buffer[0] = 0; | |
clear_lcd_buffer[1] = 1; | |
lcd_raw_write(&clear_lcd_buffer[0], sizeof(clear_lcd_buffer)); | |
while (lcd_busy()) {} | |
} | |
void lcd_blank(uint8_t *chars) { | |
int i; | |
for (i = 0; i < 32; i++) { | |
chars[i] = ' '; | |
} | |
} | |
void lcd_write(uint8_t *chars) { | |
uint8_t buf[57]; | |
buf[0] = 0x40; | |
// Loop over buffer. Put provided 32-element chars in correct | |
// memory addresses (there are 24 bytes of memory between the rows). | |
int i, v; | |
for (i = 0; i < 56; i++) { | |
if (i < 16) { | |
v = chars[i]; | |
} else if (i >= 40) { | |
v = chars[i - 24]; | |
} else { | |
v = ' '; | |
} | |
buf[i + 1] = ASCII_OFFSET + v; | |
} | |
lcd_raw_write(buf, sizeof(buf)); | |
} | |
void lcd_goto(int row, int column) { | |
uint8_t buf[2]; | |
buf[0] = 0x00; | |
buf[1] = 0x80 + (row * 0x40) + column; | |
lcd_raw_write(buf, sizeof(buf)); | |
} | |
void a2d_init() { | |
PINSEL_CFG_Type PinCfg; | |
/* Because the potentiometer on different boards (MCB & IAR) connect | |
* with different ADC channel, so we have to configure correct ADC channel | |
* o while(adc_value==0);n each board respectively. | |
* If you want to check other ADC channels, you have to wire this ADC pin directly | |
* to potentiometer pin (please see schematic doc for more reference) | |
*/ | |
#ifdef MCB_LPC_1768 | |
/* If using MCB1700 v.1 board | |
* select P0.25 as AD0.2 | |
*/ | |
PinCfg.Funcnum = 1; | |
PinCfg.OpenDrain = 0; | |
PinCfg.Pinmode = 0; | |
PinCfg.Pinnum = 25; | |
PinCfg.Portnum = 0; | |
PINSEL_ConfigPin(&PinCfg); | |
#elif defined(IAR_LPC_1768) | |
/* If using IAR LPC1768 KS v.A board: | |
* select P1.31 as AD0.5 | |
*/ | |
PinCfg.Funcnum = 3; | |
PinCfg.OpenDrain = 0; | |
PinCfg.Pinmode = 0; | |
PinCfg.Pinnum = 31; | |
PinCfg.Portnum = 1;char digits[15]; | |
int digiti; | |
for (digiti = 0; digiti < 14; digiti++) { | |
digits[digiti] = '0'; | |
} | |
digits[14] = 0; | |
int k = 2; | |
if (percent >= 1) { | |
digits[0] = '1'; | |
} else { | |
digits[0] = '0'; | |
digits[1] = '.'; | |
float t = percent; | |
while (t > 0 && k <= 13) { | |
t = t * 10; | |
int ti = (int) t; | |
t -= ti; | |
digits[k] = ti + '0'; | |
k++; | |
} | |
} | |
tty_writeln(digits); | |
PINSEL_ConfigPin(&PinCfg); | |
#endif | |
} | |
int get_int_bit(int v, int n) { | |
return (v & 1<<n) >> n; | |
} | |
void d2a_init() { | |
PINSEL_CFG_Type PinCfg; | |
PinCfg.Funcnum = 2; | |
PinCfg.OpenDrain = 0; | |
PinCfg.Pinmode = 0; | |
PinCfg.Pinnum = 26; | |
PinCfg.Portnum = 0; | |
PINSEL_ConfigPin(&PinCfg); | |
} | |
float sucapp_to_percent(uint32_t sucapp) { | |
int b; | |
float percent = 0; | |
float m = 0.5; | |
for (b = 11; b >= 0; b--) { | |
int bit = get_int_bit(sucapp, b); | |
if (bit == 1) { | |
percent += m; | |
} | |
if (percent < 0) percent = 0; | |
m = m / 2.0; | |
} | |
return percent; | |
} | |
uint32_t percent_to_sucapp(double percent) { | |
uint32_t sucapp = 0; | |
double m = 0.5; | |
int i; | |
if (percent >= 1) { | |
percent = 0.99; | |
} | |
for (i = 7; i >= 0; i--) { | |
if (percent >= m) { | |
sucapp += 1<<i; | |
percent -= m; | |
} | |
m = m / 2.0; | |
} | |
return sucapp; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment