From: Nathael Pajani Date: Wed, 9 Sep 2015 20:10:01 +0000 (+0200) Subject: Move all base apps to a base subdirectory in apps. This prepares for merge of modules... X-Git-Url: http://git.techno-innov.fr/?a=commitdiff_plain;h=ce7f0140c7f9572621c14dc5c767c2ea75a91def;p=soft%2Flpc122x%2Fexamples Move all base apps to a base subdirectory in apps. This prepares for merge of modules branches, which will instead have their own subdirectory, preventing the hasle of cherry-picking common code to each and every branch. Warning : Makefile modifications according to these moves will be in the next commit ! --- ce7f0140c7f9572621c14dc5c767c2ea75a91def diff --git a/adc/Makefile b/adc/Makefile new file mode 100644 index 0000000..91407f3 --- /dev/null +++ b/adc/Makefile @@ -0,0 +1,10 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + +clean mrproper: + @make -C ../.. --no-print-directory $@ diff --git a/adc/README b/adc/README new file mode 100644 index 0000000..faf1d07 --- /dev/null +++ b/adc/README @@ -0,0 +1,36 @@ +ADC and TMP36 Example + +Copyright 2013 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the internal ADC, with conversion examples for +a TMP36 analog temperature sensor and a CdS photoresistor. + +The conversion results are sent on the UART0 serial line (115200 8n1) at +regular intervals, and the status led flashes the rest of the time. + +The output looks like this : + ADC(0): 684 (raw: 0x02ac) + TMP36: 29,36 (orig: 248, raw: 00f8) + +The first line displays the decimal and hexadecimal value of the raw +conversion result, on which was the luminosity sensor. +The second line displays the TMP36 temperature, which is not very acurate at +ambient temperature, with the corresponding decimal and hexadecimal raw +conversion values. diff --git a/adc/main.c b/adc/main.c new file mode 100644 index 0000000..7a8cec1 --- /dev/null +++ b/adc/main.c @@ -0,0 +1,180 @@ +/**************************************************************************** + * apps/adc/main.c + * + * ADC example + * + * Copyright 2013-2014 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "extdrv/status_led.h" +#include "drivers/adc.h" + + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + ARRAY_LAST_PIO, +}; + +const struct pio_config adc_pins[] = { + { LPC_ADC_AD0_PIO_0_30, LPC_IO_ANALOG }, + { LPC_ADC_AD1_PIO_0_31, LPC_IO_ANALOG }, + { LPC_ADC_AD2_PIO_1_0, LPC_IO_ANALOG }, + { LPC_ADC_AD3_PIO_1_1, LPC_IO_ANALOG }, + { LPC_ADC_AD4_PIO_1_2, LPC_IO_ANALOG }, + { LPC_ADC_AD5_PIO_1_3, LPC_IO_ANALOG }, + ARRAY_LAST_PIO, +}; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +/***************************************************************************** */ +/* This will display the integer value read on the ADC, between 0 and 1024. + * ADC must be initialised prior to calls to adc_display() (it means that adc_on() + * must be called before using this function. + * adc_num is an ADC channel number (integer between 0 and 7) + * use LPC_ADC_NUM(x) for channel selection. + * returns ADC convertion value or negative value on error. + */ +int adc_display(int adc_num, int uart_num) +{ + uint16_t val = 0; + int ret = 0; + + adc_start_convertion_once(adc_num, 0); + msleep(10); + ret = adc_get_value(&val, adc_num); + if (ret < 0) { + return ret; + } else { + /* Always display, even if value has already been read */ + char buff[40]; + int len = 0; + len = snprintf(buff, 40, "ADC(%d): %d (raw: 0x%04x)\r\n", adc_num, val, val); + serial_write(uart_num, buff, len); + } + return val; +} + +/* Display the temperature computed from adc convertion of the voltage output of + * a TMP36 analog temperature sensor + * ADC must be initialised prior to calls to TMP36_display() (it means that adc_on() + * must be called before using this function. + * adc_num is an ADC channel number (integer between 0 and 7) + * use LPC_ADC_NUM(x) for channel selection. + */ +void TMP36_display(int adc_num, int uart_num) +{ + uint16_t val = 0; + int ret = 0; + + adc_start_convertion_once(adc_num, 0); + msleep(8); + ret = adc_get_value(&val, adc_num); + if (ret == 0) { + char buff[60]; + int len = 0; + int micro_volts = 0; + /* depends on vref, should use a precise 3.0V Vref and multiply by 3000 */ + micro_volts = (val * 3200); + int converted = ((micro_volts / 100) - 5000); + len = snprintf(buff, 60, "TMP36: %d,%d (orig: %d, raw: %04x)\r\n", + (converted / 100), (converted % 100), val, val); + serial_write(uart_num, buff, len); + } +} + + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + set_pins(adc_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(0, name, len); + /* Wait for end of Tx */ + serial_flush(0); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + + + +/***************************************************************************** */ +int main(void) { + system_init(); + uart_on(0, 115200, NULL); + adc_on(); + + while (1) { + chenillard(500); + /* ADC Test */ + adc_display(LPC_ADC_NUM(0), 0); + TMP36_display(LPC_ADC_NUM(1), 0); + } + return 0; +} + + + diff --git a/eeprom/Makefile b/eeprom/Makefile new file mode 100644 index 0000000..91407f3 --- /dev/null +++ b/eeprom/Makefile @@ -0,0 +1,10 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + +clean mrproper: + @make -C ../.. --no-print-directory $@ diff --git a/eeprom/README b/eeprom/README new file mode 100644 index 0000000..e7460fe --- /dev/null +++ b/eeprom/README @@ -0,0 +1,24 @@ +EEPROM support example + +Copyright 2013 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the onboard I2C eeprom memory + +TODO diff --git a/eeprom/main.c b/eeprom/main.c new file mode 100644 index 0000000..24eb6d8 --- /dev/null +++ b/eeprom/main.c @@ -0,0 +1,245 @@ +/**************************************************************************** + * apps/eeprom/main.c + * + * + * + * Copyright 2013-2014 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/i2c.h" +#include "extdrv/eeprom.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "extdrv/status_led.h" + + +#ifndef MODULE_SERIAL_NUM +#define MODULE_SERIAL_NUM 10 +#endif +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define EEPROM_WRITE +#undef EEPROM_WRITE + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + /* I2C 0 */ + { LPC_I2C0_SCL_PIO_0_10, (LPC_IO_DIGITAL | LPC_IO_OPEN_DRAIN_ENABLE) }, + { LPC_I2C0_SDA_PIO_0_11, (LPC_IO_DIGITAL | LPC_IO_OPEN_DRAIN_ENABLE) }, + ARRAY_LAST_PIO, +}; + +const struct pio button_gpio = LPC_GPIO_0_12; /* ISP Used as button */ +const struct pio led_gpio = LPC_GPIO_0_4; /* Led toggle on ISP button press */ + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +const struct pio i2c_eeprom_cs = LPC_GPIO_0_15; + + +/***************************************************************************** */ +/* EEPROM support */ + +/* Module identification support for DTPlug and DomoTab */ + +/* The eeprom on the GPIO Demo module must reply on address 0xA8 */ +#define EEPROM_ADDR 0xA8 + +/* Module capabilities */ +#define UEXT_MOD_HAS_NONE 0 +#define UEXT_MOD_HAS_UART (1 << 0) +#define UEXT_MOD_HAS_I2C (1 << 1) +#define UEXT_MOD_HAS_SPI (1 << 2) + +struct module_desc { + uint16_t serial_number; + uint8_t version; + uint8_t header_size; + uint8_t capabilities; /* Bit mask of UEXT_MOD_HAS_* */ + uint8_t name_offset; + uint8_t name_size; + uint8_t image_offset; + uint16_t image_size; +} __attribute__ ((packed)); + + + +/* EEPROM Chip select for the GPIO Demo module. + * Set the SPI SSEL pin low. + * These functions are specific to the mod_gpio_demo and domotab modules which + * have access to their onboard EEPROM. + * It is used to release the gate that blocks the SCL signal to the EEPROM, + * allowing multiple eeproms with the same address to be accessed one at a time + * on the same I2C Bus, which gives a way to both identify modules presence and + * module function, name, and pther capabilities. + * When the SPI is used as slave, the master has the control of the SPI SSEL signal + * and the EEPROM should not be accessed by the module. + * Other I2C EEPROMs should not need these functions. + */ +int mod_gpio_demo_eeprom_cs_pull_low(void) +{ + /* Configure SPI_CS as output and set it low. */ + config_gpio(&i2c_eeprom_cs, 0, GPIO_DIR_OUT, 0); + return 0; +} +void mod_gpio_demo_eeprom_cs_release(void) +{ + struct lpc_gpio* gpio_port_regs = LPC_GPIO_REGS(i2c_eeprom_cs.port); + gpio_port_regs->set = (1 << i2c_eeprom_cs.pin); +} + + +/* Module description support */ + +#define DUMP_BUFF_SIZE 80 +void module_desc_dump(uint8_t serial_num) +{ + char buff[DUMP_BUFF_SIZE]; + int len = 0, ret = 0; + struct module_desc desc; + + mod_gpio_demo_eeprom_cs_pull_low(); + /* Read module descriptor structure from eeprom */ + ret = eeprom_read(EEPROM_ADDR, 0, (char*)&desc, sizeof(struct module_desc)); + if (ret != sizeof(struct module_desc)) { + mod_gpio_demo_eeprom_cs_release(); + serial_write(serial_num, "EEPROM read error\r\n", 19); + return; + } + /* Send the content of the header */ + serial_write(serial_num, "Module :\r\n", 10); + len = snprintf(buff, 16, "serial: %d, ", desc.serial_number); + len += snprintf((buff + len), 15, "ver: %d\r\n", desc.version); + len += snprintf((buff + len), 16, "cap: 0x%04x\r\n", desc.capabilities); + /* Get and send the module name */ + if (desc.name_size >= DUMP_BUFF_SIZE) { + desc.name_size = DUMP_BUFF_SIZE - len - 3; + } + ret = eeprom_read(EEPROM_ADDR, desc.name_offset, (buff + len), desc.name_size); + if (ret == desc.name_size) { + len += ret; + len += snprintf((buff + len), 3, "\r\n"); + } + ret = 0; + do { + ret += serial_write(serial_num, (buff + ret), (len - ret)); + } while (ret < len); + mod_gpio_demo_eeprom_cs_release(); +} + +int module_desc_set(char* name, uint8_t module_version, uint16_t serial_num) +{ + int ret = 0; + struct module_desc desc = { + .serial_number = serial_num, + .version = module_version, + .capabilities = (UEXT_MOD_HAS_UART | UEXT_MOD_HAS_I2C | UEXT_MOD_HAS_SPI), + .name_offset = sizeof(struct module_desc), + .image_offset = 0, + .image_size = 0, + }; + + mod_gpio_demo_eeprom_cs_pull_low(); + desc.name_size = strlen(name); + ret = eeprom_write(EEPROM_ADDR, 0, (char*)&desc, sizeof(struct module_desc)); + if (ret != sizeof(struct module_desc)) { + mod_gpio_demo_eeprom_cs_release(); + return -1; + } + ret += eeprom_write(EEPROM_ADDR, ret, name, desc.name_size); + mod_gpio_demo_eeprom_cs_release(); + return ret; +} + + +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(0, name, len); + /* Wait for end of Tx */ + serial_flush(0); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + + +/***************************************************************************** */ +int main(void) { + system_init(); + uart_on(0, 115200, NULL); + + i2c_on(I2C_CLK_100KHz); + + /* Set or read Module identification header in EEPROM */ +#ifdef EEPROM_WRITE + module_desc_set(MODULE_NAME, MODULE_VERSION, MODULE_SERIAL_NUM); +#else + module_desc_dump(0); +#endif + + while (1) { + chenillard(250); + } + return 0; +} + + diff --git a/epaper/Makefile b/epaper/Makefile new file mode 100644 index 0000000..e44d25f --- /dev/null +++ b/epaper/Makefile @@ -0,0 +1,12 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + cat $@ *.epaper > $(NAME).img + +clean mrproper: + @make -C ../.. --no-print-directory $@ + diff --git a/epaper/README b/epaper/README new file mode 100644 index 0000000..0f0ee8a --- /dev/null +++ b/epaper/README @@ -0,0 +1,45 @@ +E-paper example + +Copyright 2015 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the E-paper display from embedded Artists which is +an adapter for Pervasive Display e-ink screen. + +In order to create an image for the display, make a 264x176 image, black and white. +Using gimp, export as "Raw data image" (*.data). +In the popup, select "Standard (R, V, B)" and "R, V, B (normal)". + +Then use the programm from the image_converter sub-directory to convert to e-paper +format. (Use the Makefile in the sub-directory to compile). + +And use: +./bw_raw_data_gimp_to_bw_epaper input.data output.epaper + +Current Makefile appends all raw images (*.epaper) to the firmware binary (epaper.bin) +to generate the new binary which you should upload: epaper.img + +Current main only handles two images. +Pressing the ISP button toggles between the images. + +Data received on UART0 is displayed on the first line when either of '\r', '\n' or '\0' is +received. +The maximum size of the line is 33 characters for the 2.7" epaper deisplay. + + diff --git a/epaper/Techno-Innov_bw_epaper.epaper b/epaper/Techno-Innov_bw_epaper.epaper new file mode 100644 index 0000000..d76ebdb Binary files /dev/null and b/epaper/Techno-Innov_bw_epaper.epaper differ diff --git a/epaper/image_converter/.gitignore b/epaper/image_converter/.gitignore new file mode 100644 index 0000000..cf7077d --- /dev/null +++ b/epaper/image_converter/.gitignore @@ -0,0 +1,16 @@ +# +# NOTE! Don't add files that are generated in specific +# subdirectories here. Add them in the ".gitignore" file +# in that subdirectory instead. +# +# NOTE! Please use 'git ls-files -i --exclude-standard' +# command after changing this file, to see if there are +# any tracked files which get ignored after the change. +# +# Normal rules +# +*.o +*.d +*/objs/* +tags +bw_raw_data_gimp_to_bw_epaper diff --git a/epaper/image_converter/Makefile b/epaper/image_converter/Makefile new file mode 100644 index 0000000..aedb22f --- /dev/null +++ b/epaper/image_converter/Makefile @@ -0,0 +1,32 @@ +#CROSS_COMPILE ?= arm-linux-gnueabihf- +CC = $(CROSS_COMPILE)gcc + +CFLAGS = -Wall -O2 -Wextra + +EXEC = bw_raw_data_gimp_to_bw_epaper + +all: $(EXEC) + + +OBJDIR = objs +SRC = $(shell find . -name \*.c) +OBJS = ${SRC:%.c=${OBJDIR}/%.o} +INCLUDES = includes/ + +${OBJDIR}/%.o: %.c + @mkdir -p $(dir $@) + @echo "-- compiling" $< + @$(CC) -MMD -MP -MF ${OBJDIR}/$*.d $(CFLAGS) $< -c -o $@ -I$(INCLUDES) + +$(EXEC): $(OBJS) + @echo "Linking $@ ..." + @$(CC) $(LDFLAGS) -o $@ $(OBJS) + @echo Done. + + +clean: + find ${OBJDIR} -name "*.o" -exec rm {} \; + find ${OBJDIR} -name "*.d" -exec rm {} \; + +mrproper: clean + rm -f $(EXEC) diff --git a/epaper/image_converter/convert.c b/epaper/image_converter/convert.c new file mode 100644 index 0000000..2934418 --- /dev/null +++ b/epaper/image_converter/convert.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include + + +int main(int argc, char** argv) +{ + int source_fd = -1; + int dest_fd = -1; + char inbuff[8]; + + if (argc < 2) { + printf("Usage: %s input_file output_file\n", argv[0]); + } + + source_fd = open(argv[1], O_RDONLY); + dest_fd = open(argv[2], (O_RDWR | O_CREAT), (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)); + + if ((source_fd < 0) || (dest_fd < 0)) { + printf("unable to open input or output file\n"); + } + + while (read(source_fd, inbuff, 8) == 8) { + int i = 0; + char outbuff = 0; + for (i = 0; i < 8; i++) { + outbuff |= ((inbuff[i] & 0x01) << i); + } + write(dest_fd, &outbuff, 1); + } + + close(source_fd); + close(dest_fd); + + return 0; +} diff --git a/epaper/main.c b/epaper/main.c new file mode 100644 index 0000000..7633ea5 --- /dev/null +++ b/epaper/main.c @@ -0,0 +1,261 @@ +/**************************************************************************** + * apps/epaper/main.c + * + * e-paper example + * + * Copyright 2013-2015 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "drivers/timers.h" +#include "extdrv/status_led.h" +#include "drivers/ssp.h" + +#include "extdrv/epaper.h" +#include "lib/font.h" + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + /* UART 1 */ + { LPC_UART1_RX_PIO_0_8, LPC_IO_DIGITAL }, + { LPC_UART1_TX_PIO_0_9, LPC_IO_DIGITAL }, + /* SPI */ + { LPC_SSP0_SCLK_PIO_0_14, LPC_IO_DIGITAL }, + { LPC_SSP0_MOSI_PIO_0_17, LPC_IO_DIGITAL }, + { LPC_SSP0_MISO_PIO_0_16, LPC_IO_DIGITAL }, + /* PWM */ +#define LPC_TIMER_PIN_CONFIG (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL | LPC_IO_DRIVE_HIGHCURENT) + { LPC_TIMER_32B0_M1_PIO_0_19, LPC_TIMER_PIN_CONFIG }, + ARRAY_LAST_PIO, +}; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +const struct pio button = LPC_GPIO_0_12; /* ISP button */ + +/* + * E-paper configuration, 2.7" size + * see Pervasive display documentation (Doc. No. 4P008-00) + */ +#define LINE_SIZE 264 +struct epaper_definition epaper_def = { + .pin_reset = LPC_GPIO_0_20, + .pin_power_ctrl = LPC_GPIO_0_21, + .pin_discharge = LPC_GPIO_0_22, + .pin_border_ctrl = LPC_GPIO_0_23, + .pin_busy = LPC_GPIO_0_24, + /* SPI */ + .pin_spi_cs = LPC_GPIO_0_15, + .spi_num = 0, + /* PWM */ + .pwm_timer_num = LPC_TIMER_32B0, + .pwm_timer_conf = { + .mode = LPC_TIMER_MODE_PWM, + /* pin PIO0_19 is channel 1 - PWM cycle control on channel 3 */ + .config = { LPC_PWM_CHANNEL_ENABLE(1), 3, 0, 0 }, + .match = { 0, 60, 0, 120 }, /* 50% duty cycle on channel 1, approx 200 KHz whith 48MHz clock */ + }, + .pixels_per_line = LINE_SIZE, + .bytes_per_line = (LINE_SIZE / 8), + .lines = 176, + .bytes_per_scan = (176 / 4), + .channel = {0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFE, 0x00, 0x00}, /* Reg 0x01 */ + .gate_source_level = 0x00, /* Reg 0x04 */ + .stage_time = 630, + .line_termination_required = 1, +}; + + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(1, name, len); + /* Wait for end of Tx */ + serial_flush(1); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + +static volatile uint8_t white_request = 0; +void button_request(uint32_t gpio) { + white_request = 1; +} + +extern unsigned int _sram_base; +extern unsigned int _end_text; +extern unsigned int _end_data; + + +#define TEXT_LENGTH_MAX 33 +static volatile uint8_t display_text_buff[TEXT_LENGTH_MAX]; +static volatile uint8_t update_text = 0; +void recv_text(uint8_t c) +{ + static uint8_t idx = 0; + static uint8_t rx_buff[TEXT_LENGTH_MAX]; + rx_buff[idx++] = c; + if ((c == '\0') || (c == '\r') || (c == '\n')) { + update_text = 1; + rx_buff[idx++] = '\0'; + memcpy((void*)display_text_buff, rx_buff, idx); + idx = 0; + } +} + +void build_line(uint8_t* img_buff, uint8_t* text) +{ + int i = 0, line = 0; + int len = strlen((char*)text); + + for (i = 0; i < len; i++) { + uint8_t tile = (text[i] > first_font_char) ? (text[i] - first_font_char) : 0; + uint8_t* tile_data = (uint8_t*)(&font[tile]); + for (line = 0; line < 8; line++) { + img_buff[ (line * epaper_def.bytes_per_line) + i ] = tile_data[7 - line]; + } + } +} + + +/* FIXME : + * Actual font data is stored in "human drawing order", but must be sent in revers bit order. + * This function takes care of bit reversal for each font byte once and for all. + * This should be done on the font file for execution efficiency and code size, but would make + * font update harder. + */ +void fix_font(uint64_t* font_64, uint8_t size) +{ + int i = 0; + uint32_t* f = (uint32_t*)font_64; + size = size * 2; + for (i = 0; i < size; i++) { + // swap odd and even bits + f[i] = ((f[i] >> 1) & 0x55555555) | ((f[i] & 0x55555555) << 1); + // swap consecutive pairs + f[i] = ((f[i] >> 2) & 0x33333333) | ((f[i] & 0x33333333) << 2); + // swap nibbles ... + f[i] = ((f[i] >> 4) & 0x0F0F0F0F) | ((f[i] & 0x0F0F0F0F) << 4); + } +} + +/***************************************************************************** */ +#define BUFF_LEN 60 +int main(void) { + + system_init(); + uart_on(0, 115200, recv_text); + ssp_master_on(0, LPC_SSP_FRAME_SPI, 8, 8*1000*1000); /* bus_num, frame_type, data_width, rate */ + set_gpio_callback(button_request, &button, EDGE_RISING); + status_led(none); + + /* E-Paper */ + epaper_config(&epaper_def); + /* Font fix */ + fix_font(font, NB_FONT_TILES); + + while (1) { + if (white_request == 1) { + static int img_num = 0; + uint8_t* images = (uint8_t*)(&_end_text + (&_end_data - &_sram_base)); + uint8_t* image = (images + ((img_num % 2) * (epaper_def.bytes_per_line * epaper_def.lines))); + + status_led(green_only); + + epaper_on(); + /* Blank screen */ + epaper_uniform_display(0xAA); /* White */ + /* epaper_uniform_display(0xFF); */ /* Black */ + /* Send image */ + epaper_send_frame(image, epaper_normal); + epaper_off(); + + white_request = 0; + update_text = 1; + img_num = ((img_num + 1) % 2); + } + + if (update_text == 1) { + uint8_t white_line[LINE_SIZE] = {0}; /* ((LINE_SIZE / 8) * 8) */ + uint8_t buffer_line[LINE_SIZE] = {0}; /* ((LINE_SIZE / 8) * 8) */ + + build_line(buffer_line, (uint8_t*)display_text_buff); + + epaper_on(); + /* Blank text line */ + epaper_send_partial_frame(white_line, 0, 8, epaper_normal); + /* Real text line */ + epaper_send_partial_frame(buffer_line, 0, 8, epaper_normal); + epaper_off(); + + update_text = 0; + } + } + return 0; +} + + + + diff --git a/epaper/tibug_bw_epaper.epaper b/epaper/tibug_bw_epaper.epaper new file mode 100644 index 0000000..a7730ed Binary files /dev/null and b/epaper/tibug_bw_epaper.epaper differ diff --git a/gpio_intr/Makefile b/gpio_intr/Makefile new file mode 100644 index 0000000..91407f3 --- /dev/null +++ b/gpio_intr/Makefile @@ -0,0 +1,10 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + +clean mrproper: + @make -C ../.. --no-print-directory $@ diff --git a/gpio_intr/README b/gpio_intr/README new file mode 100644 index 0000000..e6657af --- /dev/null +++ b/gpio_intr/README @@ -0,0 +1,25 @@ +GPIO interrupt Example + +Copyright 2015 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the gpio interrupts from an external button. + +The "chenillard" is playing in an endless loop, but a release of the ISP button will +stop it for 5 seconds. diff --git a/gpio_intr/main.c b/gpio_intr/main.c new file mode 100644 index 0000000..7ea3ad0 --- /dev/null +++ b/gpio_intr/main.c @@ -0,0 +1,124 @@ +/**************************************************************************** + * apps/gpio_intr/main.c + * + * GPIO interrupt example + * + * Copyright 2013-2014 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +/* ISP button release disables the chenillard for 5 seconds */ + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "extdrv/status_led.h" + + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + ARRAY_LAST_PIO, +}; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +const struct pio button = LPC_GPIO_0_12; /* ISP button */ + + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(0, name, len); + /* Wait for end of Tx */ + serial_flush(0); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + + +uint8_t chenillard_activation_request = 0; +void activate_chenillard(uint32_t gpio) { + chenillard_activation_request = 1; +} + + +/***************************************************************************** */ +int main(void) { + system_init(); + uart_on(0, 115200, NULL); + + /* Activate the chenillard on Rising edge (button release) */ + set_gpio_callback(activate_chenillard, &button, EDGE_RISING); + + while (1) { + chenillard(250); + if (chenillard_activation_request == 1) { + status_led(none); + msleep(5000); + chenillard_activation_request = 0; + } + } + return 0; +} + + + diff --git a/i2c_temp/Makefile b/i2c_temp/Makefile new file mode 100644 index 0000000..91407f3 --- /dev/null +++ b/i2c_temp/Makefile @@ -0,0 +1,10 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + +clean mrproper: + @make -C ../.. --no-print-directory $@ diff --git a/i2c_temp/README b/i2c_temp/README new file mode 100644 index 0000000..621b7ed --- /dev/null +++ b/i2c_temp/README @@ -0,0 +1,33 @@ +TMP101 I2C temperature sensor example + +Copyright 2013 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the TMP101 I2C temperature sensor used on the +GPIO Demo module. + + +Periodic temperature conversions (decimal velue and raw conversion value) are +sent on UART0 using the following frame format : +Temp read: 27,3 - raw: 0x1b60. + +FIXME : Add support for the alert pin of the TMP101 temperature sensor. +Send an alert on both UART0 and UART1 +Stop the chenillard as long as the alert condition is present. + diff --git a/i2c_temp/main.c b/i2c_temp/main.c new file mode 100644 index 0000000..8f3f3ff --- /dev/null +++ b/i2c_temp/main.c @@ -0,0 +1,167 @@ +/**************************************************************************** + * apps/i2c_temp/main.c + * + * TMP101 I2C temperature sensor example + * + * Copyright 2013-2014 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/i2c.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "extdrv/status_led.h" +#include "extdrv/tmp101_temp_sensor.h" + + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + /* I2C 0 */ + { LPC_I2C0_SCL_PIO_0_10, (LPC_IO_DIGITAL | LPC_IO_OPEN_DRAIN_ENABLE) }, + { LPC_I2C0_SDA_PIO_0_11, (LPC_IO_DIGITAL | LPC_IO_OPEN_DRAIN_ENABLE) }, + ARRAY_LAST_PIO, +}; + +#define TMP101_ADDR 0x94 +struct tmp101_sensor_config tmp101_sensor = { + .addr = TMP101_ADDR, + .resolution = TMP_RES_ELEVEN_BITS, +}; + +const struct pio temp_alert = LPC_GPIO_0_7; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +/***************************************************************************** */ +/* Temperature */ +/* The Temperature Alert pin is on GPIO Port 0, pin 7 (PIO0_7) */ +/* The I2C Temperature sensor is at address 0x94 */ +void WAKEUP_Handler(void) +{ +} + +void temp_config(uint8_t addr, int uart_num) +{ + int ret = 0; + + /* Temp Alert */ + config_gpio(&temp_alert, LPC_IO_MODE_PULL_UP, GPIO_DIR_IN, 0); + /* FIXME : add a callback on temp_alert edge */ + + /* Temp sensor */ + ret = tmp101_sensor_config(&tmp101_sensor); + if (ret != 0) { + serial_write(uart_num, "Temp config error\r\n", 19); + } +} + +void temp_display(uint8_t addr, int uart_num) +{ + char buff[40]; + uint16_t raw = 0; + int deci_degrees = 0; + int len = 0; + + tmp101_sensor_start_conversion(&tmp101_sensor); + msleep(250); /* Wait for the end of the conversion : 40ms */ + len = tmp101_sensor_read(&tmp101_sensor, &raw, &deci_degrees); + if (len != 0) { + serial_write(uart_num, "Temp read error\r\n", 19); + } else { + len = snprintf(buff, 40, "Temp read: %d,%d - raw: 0x%04x.\r\n", + (deci_degrees/10), (deci_degrees%10), raw); + serial_write(uart_num, buff, len); + } +} + + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(1, name, len); + /* Wait for end of Tx */ + serial_flush(1); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + + + +/***************************************************************************** */ +int main(void) { + system_init(); + uart_on(0, 115200, NULL); + + i2c_on(I2C_CLK_100KHz); + + /* Configure onboard temp sensor */ + temp_config(TMP101_ADDR, 0); + + while (1) { + chenillard(250); + temp_display(TMP101_ADDR, 0); + } + return 0; +} + diff --git a/lcd_char/Makefile b/lcd_char/Makefile new file mode 100644 index 0000000..86e0d12 --- /dev/null +++ b/lcd_char/Makefile @@ -0,0 +1,11 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + +clean mrproper: + @make -C ../.. --no-print-directory $@ + diff --git a/lcd_char/README b/lcd_char/README new file mode 100644 index 0000000..1c64cd2 --- /dev/null +++ b/lcd_char/README @@ -0,0 +1,47 @@ +LCD Character display example + +Copyright 2015 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the LCD Character displays compatible with the +Hitachi HD44780 driver. +This demo application has also been used to test the Max31588 thermocouple to digital +converter. + + +The demo uses two LCD Character displays, one 20x4 characters connected using 8 data +lines, and a second 16x2 characters display connected using 4 data lines. + +Upon start both displays should print "Techno-Innov". + +Data received on UART0 is displayed on the "next" line of the first display as it is +received, unless it starts with character '/', in which case it goes on the second line +of the second display. + +The first line of the second display is used to display the temperature read from the +Max31588 over SPI. + + +Note : +Some functions of the lcd_char library have not been tested. +The "busy bit" reading is not working properly (always returned as not busy). +Data reading has not been tested. +Moving the cursor or the display has not been tested either. + + diff --git a/lcd_char/main.c b/lcd_char/main.c new file mode 100644 index 0000000..c1859a8 --- /dev/null +++ b/lcd_char/main.c @@ -0,0 +1,275 @@ +/**************************************************************************** + * apps/lcd_char/main.c + * + * LCD Character Display example + * + * Copyright 2013-2015 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "drivers/timers.h" +#include "extdrv/status_led.h" +#include "drivers/ssp.h" + +#include "extdrv/lcd_char.h" +#include "extdrv/max31855_thermocouple.h" + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + /* SPI */ + { LPC_SSP0_SCLK_PIO_0_14, LPC_IO_DIGITAL }, + { LPC_SSP0_MOSI_PIO_0_17, LPC_IO_DIGITAL }, + { LPC_SSP0_MISO_PIO_0_16, LPC_IO_DIGITAL }, + ARRAY_LAST_PIO, +}; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +const struct pio button = LPC_GPIO_0_12; /* ISP button */ + + +/* Thermocouple reading */ +const struct max31855_sensor_config thermo = { + .ssp_bus_num = 0, + .chip_select = LPC_GPIO_0_15, +}; + +/* + * LCD Character display configuration + */ +#define TEXT_LENGTH_MAX_LCD_ONE 20 +struct lcdc_definition lcd_one = { + /* Control pins */ + .pin_reg_sel = LPC_GPIO_0_19, + .pin_rw_sel = LPC_GPIO_0_20, + .pin_enable = LPC_GPIO_0_21, + /* Data pins */ + .data_pins = { + LPC_GPIO_0_22, + LPC_GPIO_0_23, + LPC_GPIO_0_24, + LPC_GPIO_0_25, + LPC_GPIO_0_26, + LPC_GPIO_0_27, + LPC_GPIO_0_28, + LPC_GPIO_0_29, + }, + .nb_lines = 4, + .bytes_per_line = TEXT_LENGTH_MAX_LCD_ONE, + .eight_bits_mode = LCDC_DATA_IS_EIGTH_BITS, + .font_size = LCDC_FONT_EIGHT_DOTS, + .increment_type = LCDC_MODE_INCREMENT, + .auto_display_shift = 0, +}; +#define TEXT_LENGTH_MAX_LCD_TWO 16 +struct lcdc_definition lcd_two = { + /* Control pins */ + .pin_reg_sel = LPC_GPIO_0_3, + .pin_rw_sel = LPC_GPIO_0_4, + .pin_enable = LPC_GPIO_0_5, + /* Data pins */ + .data_pins = { + LPC_GPIO_0_6, + LPC_GPIO_0_7, + LPC_GPIO_0_8, + LPC_GPIO_0_9, + }, + .nb_lines = 2, + .bytes_per_line = TEXT_LENGTH_MAX_LCD_TWO, + .eight_bits_mode = LCDC_DATA_IS_FOUR_BITS, + .font_size = LCDC_FONT_EIGHT_DOTS, + .increment_type = LCDC_MODE_INCREMENT, + .auto_display_shift = 0, +}; + + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(1, name, len); + /* Wait for end of Tx */ + serial_flush(1); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + +static volatile uint8_t clear_request = 0; +void button_request(uint32_t gpio) { + clear_request = 1; +} + + +static volatile uint8_t display_text_buff[TEXT_LENGTH_MAX_LCD_ONE]; +static volatile uint8_t update_text = 0; +void recv_text(uint8_t c) +{ + static uint8_t idx = 0; + static uint8_t rx_buff[TEXT_LENGTH_MAX_LCD_ONE]; + rx_buff[idx++] = c; + if ((c == '\0') || (c == '\r') || (c == '\n')) { + update_text = 1; + rx_buff[(idx - 1)] = ' '; + memcpy((void*)display_text_buff, rx_buff, idx); + idx = 0; + } + if (idx >= TEXT_LENGTH_MAX_LCD_ONE) { + idx = 0; + } +} + + +#define TEMP_CYCLE_DELAY 1000 +/***************************************************************************** */ +int main(void) +{ + int get_temp = 0; + + system_init(); + uart_on(0, 115200, recv_text); + ssp_master_on(thermo.ssp_bus_num, LPC_SSP_FRAME_SPI, 8, 4*1000*1000); + set_gpio_callback(button_request, &button, EDGE_RISING); + status_led(none); + + /* Thermocouple configuration */ + max31855_sensor_config(&thermo); + uprintf(0, "Thermocouple config OK\n"); + + /* LCD Character display configuration */ + lcdc_config(&lcd_one); + lcdc_init(&lcd_one); + lcdc_config(&lcd_two); + lcdc_init(&lcd_two); + uprintf(0, "Displays Init OK\n"); + + /* Turn displays on */ + lcdc_on_off(&lcd_one, 1, 0, 0); /* ON, Cursor underline off, Cursor blink off */ + lcdc_on_off(&lcd_two, 1, 0, 1); /* ON, Cursor underline off, Cursor blink on */ + uprintf(0, "Displays ON\n"); + + lcdc_move_cursor_home(&lcd_one); + lcdc_move_cursor_home(&lcd_two); + uprintf(0, "Cursors at home\n"); + + lcdc_send_data_line(&lcd_one, 0, (uint8_t*)"Techno-Innov", 12); + lcdc_send_data_line(&lcd_two, 1, (uint8_t*)"Techno-Innov", 12); + memset((void*)display_text_buff, ' ', TEXT_LENGTH_MAX_LCD_ONE); + + while (1) { + if (clear_request == 1) { + /* Only clear LCD "one" */ + lcdc_clear(&lcd_one); + lcdc_move_cursor_home(&lcd_one); + clear_request = 0; + } + if (update_text == 1) { + static int line_lcd_one = 1; + static int line_lcd_two = 1; + if (display_text_buff[0] != '/') { + lcdc_send_data_line(&lcd_one, line_lcd_one, (uint8_t*)display_text_buff, lcd_one.bytes_per_line); + memset((void*)display_text_buff, ' ', TEXT_LENGTH_MAX_LCD_ONE); + line_lcd_one++; + if (line_lcd_one >= lcd_one.nb_lines) { + line_lcd_one = 0; + } + } else { + lcdc_send_data_line(&lcd_two, line_lcd_two, (uint8_t*)display_text_buff, lcd_two.bytes_per_line); + memset((void*)display_text_buff, ' ', TEXT_LENGTH_MAX_LCD_ONE); + line_lcd_two++; + if (line_lcd_two >= lcd_two.nb_lines) { + line_lcd_two = 1; /* Keep first line for temperature */ + } + } + update_text = 0; + } + if (get_temp++ == TEMP_CYCLE_DELAY) { + int centi_degrees = 0, ret = 0; + ret = max31855_sensor_read(&thermo, NULL, ¢i_degrees); + if (ret != 0) { + lcdc_send_data_line(&lcd_two, 0, (uint8_t*)"Temp err", 8); + } else { + char buff[10]; + int abs_centi = centi_degrees; + int len = 0; + if (centi_degrees < 0) { + abs_centi = -centi_degrees; + } + len = snprintf(buff, 10, "% 4d.%02d ", (centi_degrees / 100), (abs_centi % 100)); + buff[len] = ' '; + lcdc_send_data_line(&lcd_two, 0, (uint8_t*)buff, 8); + lcdc_write(&lcd_two, 0xDF); + lcdc_write(&lcd_two, 'C'); + } + get_temp = 0; + } else { + msleep(1); + } + } + return 0; +} + + + + diff --git a/ledstrip/Makefile b/ledstrip/Makefile new file mode 100644 index 0000000..91407f3 --- /dev/null +++ b/ledstrip/Makefile @@ -0,0 +1,10 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + +clean mrproper: + @make -C ../.. --no-print-directory $@ diff --git a/ledstrip/README b/ledstrip/README new file mode 100644 index 0000000..180ed2e --- /dev/null +++ b/ledstrip/README @@ -0,0 +1,43 @@ +WS2812 Chainable leds example + +Copyright 2015 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the WS2812 chainable leds. +It has been tested using a 60 leds strip from Adafruit. + +WS2812 external driver development is based on data found in the WS2812.pdf +datasheet provided by Adafruit : https://www.adafruit.com/datasheets/WS2812.pdf + + +The external driver (extdrv/ws2812.[ch]) provides an internal buffer which size +is defined in extdrv/ws2812.h (NB_LEDS) +This buffer is filled using ws2812_set_pixel(), and the led values are sent to +the led strip using ws2812_send_frame(). + + +This example uses the driver and adds some filling functions selected by the +module ISP button or commands received on UART0 serial line. +Leds data is generated by the filling functions either from pre-defined +patterns or using ADC samples or UART received data. +Not all functions have been implemented yet. + +TODO : Implement other functions / modes. + + diff --git a/ledstrip/main.c b/ledstrip/main.c new file mode 100644 index 0000000..0b830f0 --- /dev/null +++ b/ledstrip/main.c @@ -0,0 +1,194 @@ +/**************************************************************************** + * apps/ledstrip/main.c + * + * WS2812 Chainable leds example using Adafruit les strip + * + * Copyright 2013-2015 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "drivers/adc.h" +#include "extdrv/status_led.h" + +#include "extdrv/ws2812.h" + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + /* UART 1 */ + { LPC_UART1_RX_PIO_0_8, LPC_IO_DIGITAL }, + { LPC_UART1_TX_PIO_0_9, LPC_IO_DIGITAL }, + /* SPI */ + { LPC_SSP0_SCLK_PIO_0_14, LPC_IO_DIGITAL }, + { LPC_SSP0_MOSI_PIO_0_17, LPC_IO_DIGITAL }, + { LPC_SSP0_MISO_PIO_0_16, LPC_IO_DIGITAL }, + /* ADC */ + { LPC_ADC_AD0_PIO_0_30, LPC_IO_ANALOG }, + { LPC_ADC_AD1_PIO_0_31, LPC_IO_ANALOG }, + { LPC_ADC_AD2_PIO_1_0, LPC_IO_ANALOG }, + /* GPIO */ + { LPC_GPIO_0_19, (LPC_IO_MODE_PULL_UP | LPC_IO_DIGITAL) }, + ARRAY_LAST_PIO, +}; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +const struct pio button = LPC_GPIO_0_12; /* ISP button */ +const struct pio ws2812_data_out_pin = LPC_GPIO_0_19; /* Led control data pin */ + + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(1, name, len); + /* Wait for end of Tx */ + serial_flush(1); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + + +enum all_modes { + adc_colors = 0, + random_colors, + single_color_grade_red, + single_color_grade_green, + single_color_grade_blue, + color_grade_red_from_adc, + color_grade_green_from_adc, + color_grade_blue_from_adc, + full_grade, + moving_dot_adc_color, + serial_controlled, + white, +}; +static volatile uint8_t new_mode = 0; +void button_request(uint32_t gpio) { + new_mode++; +} + + +/* This mode reads values from ADC[0:2] every 150ms and uses the values to set the leds. + * Pixels are updated when all pixel are set from ADC input. + */ +void mode_adc_colors(void) +{ + static uint8_t pixel = 0; + uint16_t red = 0, green = 0, blue = 0; + + /* Get ADC values */ + adc_get_value(&red, LPC_ADC_NUM(0)); + adc_get_value(&green, LPC_ADC_NUM(1)); + adc_get_value(&blue, LPC_ADC_NUM(2)); + /* Set one pixel */ + ws2812_set_pixel(pixel++, ((red >> 2) & 0xFF), ((green >> 2) & 0xFF), ((blue >> 2) & 0xFF)); + /* Give some time for the ADC value to change (potentiometers should be connected to ADC inputs) */ + msleep(150); + /* give some feedback that something is going on */ + status_led(green_toggle); + /* Buffer full, send it ! */ + if (pixel >= NB_LEDS) { + ws2812_send_frame(0); + pixel = 0; + } +} + +void strip_control(uint8_t c) +{ +} + +/***************************************************************************** */ +int main(void) +{ + + system_init(); + uart_on(0, 115200, strip_control); + set_gpio_callback(button_request, &button, EDGE_RISING); + status_led(none); + + /* ADC for potentiometer color settings */ + adc_on(); + adc_start_burst_conversion(LPC_ADC_CHANNEL(0) | LPC_ADC_CHANNEL(1) | LPC_ADC_CHANNEL(2)); + + /* Led strip configuration */ + ws2812_config(&ws2812_data_out_pin); + + while (1) { + switch (new_mode) { + case adc_colors: + mode_adc_colors(); + break; + default: + ws2812_stop(); + msleep(1500); + new_mode = 0; + } + } + return 0; +} + + + + diff --git a/ultrasonic_sensor/Makefile b/ultrasonic_sensor/Makefile new file mode 100644 index 0000000..91407f3 --- /dev/null +++ b/ultrasonic_sensor/Makefile @@ -0,0 +1,10 @@ +# Makefile for GPIO Demo Module apps + +NAME = $(shell basename $(CURDIR)) + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../.. --no-print-directory NAME=$(NAME) apps/$(NAME)/$@ + +clean mrproper: + @make -C ../.. --no-print-directory $@ diff --git a/ultrasonic_sensor/README b/ultrasonic_sensor/README new file mode 100644 index 0000000..3152862 --- /dev/null +++ b/ultrasonic_sensor/README @@ -0,0 +1,29 @@ +Ultrasonic range measurement module Example + +Copyright 2015 Nathael Pajani + + +/* **************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +This example shows the support of the ultrasonic range measurement module from Seeed studio : +http://www.seeedstudio.com/wiki/index.php?title=Ultra_Sonic_range_measurement_module + +The distance is sent over UART0 every 50ms. + +Note tha for the tests the ultrasonic module is powered at 3.3V and that the right distance +is given by dividing the pulse width by 29 instead of 58 (value given on the ultrasonic +module wiki page). diff --git a/ultrasonic_sensor/main.c b/ultrasonic_sensor/main.c new file mode 100644 index 0000000..2a6112a --- /dev/null +++ b/ultrasonic_sensor/main.c @@ -0,0 +1,174 @@ +/**************************************************************************** + * apps/ultrasonic_sensor/main.c + * + * Ultrasonic range measurement example + * + * Copyright 2013-2014 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + +/* Support for ultrasonic range measurement module. + * Refer to readme file for further information. + */ + +#include +#include "core/lpc_regs_12xx.h" +#include "core/lpc_core_cm0.h" +#include "core/pio.h" +#include "core/system.h" +#include "core/systick.h" +#include "lib/stdio.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" +#include "extdrv/status_led.h" + + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + ARRAY_LAST_PIO, +}; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +const struct pio sensor = LPC_GPIO_0_7; /* Ultrasonic sensor signal */ + + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + stop_watchdog(); /* Do it right now, before it gets a chance to break in */ + + /* Note: Brown-Out detection must be powered to operate the ADC. adc_on() will power + * it back on if called after system_init() */ + system_brown_out_detection_config(0); + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + +/* Define our fault handler. This one is not mandatory, the dummy fault handler + * will be used when it's not overridden here. + * Note : The default one does a simple infinite loop. If the watchdog is deactivated + * the system will hang. + */ +void fault_info(const char* name, uint32_t len) +{ + serial_write(0, name, len); + /* Wait for end of Tx */ + serial_flush(0); + /* FIXME : Perform soft reset of the micro-controller ! */ + while (1); +} + + +/* Note that clock cycles counter wraps every 89 seconds with system clock running at 48 MHz */ +static volatile uint32_t pulse_start = 0; /* Clock cycles counter upon echo start */ +static volatile uint32_t pulse_end = 0; /* Clock cycles counter upon echo end */ +static volatile uint32_t pulse_duration = 0; +void pulse_feedback(uint32_t gpio) { + static uint32_t pulse_state = 0; + if (pulse_state == 0) { + pulse_start = systick_get_clock_cycles(); + pulse_state = 1; + } else { + pulse_end = systick_get_clock_cycles(); + if (pulse_end > pulse_start) { + pulse_duration = (pulse_end - pulse_start); + } else { + pulse_duration = (0xFFFFFFFF - pulse_start); + pulse_duration += pulse_end; + } + pulse_state = 0; + } +} + +/* Delay between measures should be at least 50ms */ +#define DELAY 50 + +/***************************************************************************** */ +int main(void) { + char buff[60]; + int len = 0; + uint32_t next_time = 0; + uint32_t delay = 0; + + system_init(); + uart_on(0, 115200, NULL); + next_time = systick_get_tick_count(); + + /* Callback on pulse start and end */ + set_gpio_callback(pulse_feedback, &sensor, EDGES_BOTH); + + while (1) { + uint32_t distance = 0; + + /* Initiate distance mesurement */ + gpio_dir_out(sensor); + gpio_clear(sensor); + usleep(10); + gpio_set(sensor); + usleep(10); + gpio_clear(sensor); + gpio_dir_in(sensor); + pulse_duration = 0; + + /* Wait for value to be available */ + while (pulse_duration == 0) { + msleep(1); + } + /* Convert pulse width in us to distance in mm */ + distance = ((pulse_duration * 10) / (get_main_clock() / (1000*1000))); + distance = distance / 29; + /* Send value on serial */ + len = snprintf(buff, 60, "dist: %dmm\n", distance); + serial_write(0, buff, len); + + /* And wait at least 50ms between loops */ + delay = next_time - systick_get_tick_count(); + if (delay > DELAY) { + delay = DELAY; + } + msleep(delay); + next_time += DELAY; + } + return 0; +} + + +