From 4defd3e1d277019c21e7404d1af04f95f33ea95c Mon Sep 17 00:00:00 2001 From: cmcmanis Date: Sun, 9 Feb 2014 13:24:48 -0800 Subject: [PATCH] The SPI-MEMS example, its not great but it does use the SPI port and can tell you the temperature of the room you are in. --- examples/stm32/f4/stm32f4-disco/README | 40 +++ examples/stm32/f4/stm32f4-disco/spi/Makefile | 7 + examples/stm32/f4/stm32f4-disco/spi/README | 17 + examples/stm32/f4/stm32f4-disco/spi/clock.c | 70 ++++ examples/stm32/f4/stm32f4-disco/spi/clock.h | 15 + examples/stm32/f4/stm32f4-disco/spi/console.c | 232 +++++++++++++ examples/stm32/f4/stm32f4-disco/spi/console.h | 54 ++++ .../stm32/f4/stm32f4-disco/spi/spi-mems.c | 304 ++++++++++++++++++ 8 files changed, 739 insertions(+) create mode 100644 examples/stm32/f4/stm32f4-disco/README create mode 100644 examples/stm32/f4/stm32f4-disco/spi/Makefile create mode 100644 examples/stm32/f4/stm32f4-disco/spi/README create mode 100644 examples/stm32/f4/stm32f4-disco/spi/clock.c create mode 100644 examples/stm32/f4/stm32f4-disco/spi/clock.h create mode 100644 examples/stm32/f4/stm32f4-disco/spi/console.c create mode 100644 examples/stm32/f4/stm32f4-disco/spi/console.h create mode 100644 examples/stm32/f4/stm32f4-disco/spi/spi-mems.c diff --git a/examples/stm32/f4/stm32f4-disco/README b/examples/stm32/f4/stm32f4-disco/README new file mode 100644 index 0000000..6ae9cb5 --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/README @@ -0,0 +1,40 @@ +README +------ + +These examples are designed to demonstrate the use of libopencm3 +with the STM32F4Discovery-DISCO board. This board has a 2.2" +TFT LCD touchscreen on it, a MEMS gyroscope, and 8MB of SDRAM. + +If you move through the examples in this order, the code from +the previous example will be used in the next example: + +0) blink - verify that you can build a program, link it, and + download it to the board. Blinks the GREEN LED at about + 2Hz + +1) systick_blink - Clock setup, Systick setup, LED GPIO setup + and blinking. + +2) usart - Program a USART on the board as a console (requires + a digital to serial adapter) + +3) usart-irq - Program a USART on the board as a console with + an interrupt driven receive routine. This allows you to + interrupt execution with ^C as you can on a Linux process. + +4) sdram - SDRAM setup, using the usb port as a console, which + sets up the SDRAM + +5) spi - Serial Peripheral Interface example which talks to + the MEMS gyroscope on the DISCO board. + +6) lcd-serial - Activates the TFT using the SPI port (serial) and + holds a frame buffer in the SDRAM area. + +7) lcd - Now uses the new LCD "driver" peripheral to refresh + the contents with what is in memory, very fast, write in + memory and it appears on screen. + +8) dma2d - The 2D graphics accelerator device which displays + various animations on the LCD using code from all of the + previous examples. diff --git a/examples/stm32/f4/stm32f4-disco/spi/Makefile b/examples/stm32/f4/stm32f4-disco/spi/Makefile new file mode 100644 index 0000000..3ab004c --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/spi/Makefile @@ -0,0 +1,7 @@ +OBJS = clock.o console.o + +BINARY = spi-mems + +LDSCRIPT = ../stm32f4-disco.ld + +include ../../Makefile.include diff --git a/examples/stm32/f4/stm32f4-disco/spi/README b/examples/stm32/f4/stm32f4-disco/spi/README new file mode 100644 index 0000000..af83b2b --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/spi/README @@ -0,0 +1,17 @@ +README spi-mems +--------------- + +This example sets up the SPI port which is connected to +an onboard MEMS gyroscope. It uses SPI5 which happens to +be one of the SPI ports that aren't defined for other +variants of the STM32F4 family. + +I'll confess that this mostly is a way to learn to use +the SPI port so that I can use it in the next example +with the LCD, but since the gyro was there I decided +to use it. Unfortunately I'm not at all sure how to +really use the Gyro. If you read the data sheet from +ST Micro it seems like it should do something useful +when you move the board around but I didn't achieve +that. Feel free to update this example with better +settings for the gyro chip. diff --git a/examples/stm32/f4/stm32f4-disco/spi/clock.c b/examples/stm32/f4/stm32f4-disco/spi/clock.c new file mode 100644 index 0000000..61f0f82 --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/spi/clock.c @@ -0,0 +1,70 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Chuck McManis + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* + * Now this is just the clock setup code from systick-blink as it is the + * transferrable part. + */ + +#include +#include +#include + +/* Common function descriptions */ +#include "clock.h" + +/* milliseconds since boot */ +static volatile uint32_t system_millis; + +/* Called when systick fires */ +void sys_tick_handler(void) { + system_millis++; +} + +/* simple sleep for delay milliseconds */ +void msleep(uint32_t delay) { + uint32_t wake = system_millis + delay; + while (wake > system_millis) ; +} + +/* Getter function for the current time */ +uint32_t mtime(void) { + return system_millis; +} + +/* + * clock_setup(void) + * + * This function sets up both the base board clock rate + * and a 1khz "system tick" count. The SYSTICK counter is + * a standard feature of the Cortex-M series. + */ +void clock_setup(void) +{ + /* Base board frequency, set to 168Mhz */ + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); + + /* clock rate / 168000 to get 1mS interrupt rate */ + systick_set_reload(168000); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB); + systick_counter_enable(); + + /* this done last */ + systick_interrupt_enable(); +} diff --git a/examples/stm32/f4/stm32f4-disco/spi/clock.h b/examples/stm32/f4/stm32f4-disco/spi/clock.h new file mode 100644 index 0000000..01c14ac --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/spi/clock.h @@ -0,0 +1,15 @@ +/* + * This include file describes the functions exported by clock.c + */ +#ifndef __CLOCK_H +#define __CLOCK_H + +/* + * Definitions for functions being abstracted out + */ +void msleep(uint32_t); +uint32_t mtime(void); +void clock_setup(void); + +#endif /* generic header protector */ + diff --git a/examples/stm32/f4/stm32f4-disco/spi/console.c b/examples/stm32/f4/stm32f4-disco/spi/console.c new file mode 100644 index 0000000..2e7a7a0 --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/spi/console.c @@ -0,0 +1,232 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Chuck McManis + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* + * Interrupt drive Console code (extracted from the usart-irq example) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "clock.h" +#include "console.h" + + +/* This is a ring buffer to holding characters as they are typed + * it maintains both the place to put the next character received + * from the UART, and the place where the last character was + * read by the program. See the README file for a discussion of + * the failure semantics. + */ +#define RECV_BUF_SIZE 128 // Arbitrary buffer size +char recv_buf[RECV_BUF_SIZE]; +volatile int recv_ndx_nxt; // Next place to store +volatile int recv_ndx_cur; // Next place to read + +/* For interrupt handling we add a new function which is called + * when recieve interrupts happen. The name (usart2_isr) is created + * by the irq.json file in libopencm3 calling this interrupt for + * USART2 'usart2', adding the suffix '_isr', and then weakly binding + * it to the 'do nothing' interrupt function in vec.c. + * + * By defining it in this file the linker will override that weak + * binding and instead bind it here, but you have to get the name + * right or it won't work. And you'll wonder where your interrupts + * are going. + */ +void usart2_isr(void) { + uint32_t reg; + int i; + + do { + reg = USART_SR(CONSOLE_UART); + if (reg & USART_SR_RXNE) { + recv_buf[recv_ndx_nxt] = USART_DR(CONSOLE_UART); +#ifdef RESET_ON_CTRLC + /* Check for "reset" */ + if (recv_buf[recv_ndx_nxt] == '\003') { + /* reset the system + * volatile definition of return address on the stack + * to insure it gets stored, changed to point to + * the trampoline function (do_the_nasty) which is + * required because we need to return of an interrupt + * to get the internal value of the LR register reset + * and put the processor back into "Thread" mode from + * "Handler" mode. + * + * See the PM0214 Programming Manual for Cortex M, + * pg 42, to see the format of the Cortex M4 stack after + * an interrupt or exception has occurred. + */ + volatile uint32_t *ret = (®) + 7; + + *ret = (uint32_t) &reset_handler; + return; + } +#endif + /* Check for "overrun" */ + i = (recv_ndx_nxt + 1) % RECV_BUF_SIZE; + if (i != recv_ndx_cur) { + recv_ndx_nxt = i; + } + } + } while ((reg & USART_SR_RXNE) != 0); // can read back-to-back interrupts +} + +/* + * console_putc(char c) + * + * Send the character 'c' to the USART, wait for the USART + * transmit buffer to be empty first. + */ +void console_putc(char c) { + uint32_t reg; + do { + reg = USART_SR(CONSOLE_UART); + } while ((reg & USART_SR_TXE) == 0); + USART_DR(CONSOLE_UART) = (uint16_t) c & 0xff; +} + +/* + * char = console_getc(int wait) + * + * Check the console for a character. If the wait flag is + * non-zero. Continue checking until a character is received + * otherwise return 0 if called and no character was available. + * + * The implementation is a bit different however, now it looks + * in the ring buffer to see if a character has arrived. + */ +char console_getc(int wait) { + char c = 0; + + while ((wait != 0) && (recv_ndx_cur == recv_ndx_nxt)) ; + if (recv_ndx_cur != recv_ndx_nxt) { + c = recv_buf[recv_ndx_cur]; + recv_ndx_cur = (recv_ndx_cur + 1) % RECV_BUF_SIZE; + } + return c; +} + +/* + * void console_puts(char *s) + * + * Send a string to the console, one character at a time, return + * after the last character, as indicated by a NUL character, is + * reached. + */ +void console_puts(char *s) { + while (*s != '\000') { + console_putc(*s); + /* Add in a carraige return, after sending line feed */ + if (*s == '\n') { + console_putc('\r'); + } + s++; + } +} + +/* + * int console_gets(char *s, int len) + * + * Wait for a string to be entered on the console, limited + * support for editing characters (back space and delete) + * end when a character is received. + */ +int console_gets(char *s, int len) { + char *t = s; + char c; + + *t = '\000'; + /* read until a is received */ + while ((c = console_getc(1)) != '\r') { + if ((c == '\010') || (c == '\127')) { + if (t > s) { + /* send ^H ^H to erase previous character */ + console_puts("\010 \010"); + t--; + } + } else { + *t = c; + console_putc(c); + if ((t - s) < len) { + t++; + } + } + /* update end of string with NUL */ + *t = '\000'; + } + return (t - s); +} + +/* + * console_setup(int baudrate) + * + * Set the pins and clocks to create a console that we can + * use for serial messages and getting text from the user. + */ +void console_setup(int baud) { + + /* MUST enable the GPIO clock in ADDITION to the USART clock */ + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); + + /* This example uses PD5 and PD6 for Tx and Rx respectively + * but other pins are available for this role on USART2 (our chosen + * USART) as well, such as PA2 and PA3. You can also split them + * so PA2 for Tx, PD6 for Rx but you would have to enable both + * the GPIOA and GPIOD clocks in that case + */ + gpio_mode_setup(GPIOD, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5 | GPIO6); + + /* Actual Alternate function number (in this case 7) is part + * depenedent, CHECK THE DATA SHEET for the right number to + * use. + */ + gpio_set_af(GPIOD, GPIO_AF7, GPIO5 | GPIO6); + + + /* This then enables the clock to the USART2 peripheral which is + * attached inside the chip to the APB2 bus. Different peripherals + * attach to different buses, and even some UARTS are attached to + * APB1 and some to APB2, again the data sheet is useful here. + */ + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USART2EN); + + /* Set up USART/UART parameters using the libopencm3 helper functions */ + usart_set_baudrate(CONSOLE_UART, baud); + usart_set_databits(CONSOLE_UART, 8); + usart_set_stopbits(CONSOLE_UART, USART_STOPBITS_1); + usart_set_mode(CONSOLE_UART, USART_MODE_TX_RX); + usart_set_parity(CONSOLE_UART, USART_PARITY_NONE); + usart_set_flow_control(CONSOLE_UART, USART_FLOWCONTROL_NONE); + usart_enable(CONSOLE_UART); + + /* Enable interrupts from the USART */ + nvic_enable_irq(NVIC_USART2_IRQ); + + /* Specifically enable recieve interrupts */ + usart_enable_rx_interrupt(CONSOLE_UART); +} diff --git a/examples/stm32/f4/stm32f4-disco/spi/console.h b/examples/stm32/f4/stm32f4-disco/spi/console.h new file mode 100644 index 0000000..263f186 --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/spi/console.h @@ -0,0 +1,54 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Chuck McManis + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef __CONSOLE_H +#define __CONSOLE_H + +/* + * Some definitions of our console "functions" attached to the + * USART. + * + * These define sort of the minimum "library" of functions which + * we can use on a serial port. If you wish to use a different + * USART there are several things to change: + * - CONSOLE_UART change this + * - Change the peripheral enable clock + * - add usartx_isr for interrupts + * - nvic_enable_interrupt(your choice of USART/UART) + * - GPIO pins for transmit/receive + * (may be on different alternate functions as well) + */ + + +#define CONSOLE_UART USART2 + +/* + * Our simple console definitions + */ + +void console_putc(char c); +char console_getc(int wait); +void console_puts(char *s); +int console_gets(char *s, int len); +void console_setup(int baudrate); + +/* this is for fun, if you type ^C to this example it will reset */ +#define RESET_ON_CTRLC + +#endif diff --git a/examples/stm32/f4/stm32f4-disco/spi/spi-mems.c b/examples/stm32/f4/stm32f4-disco/spi/spi-mems.c new file mode 100644 index 0000000..24899f3 --- /dev/null +++ b/examples/stm32/f4/stm32f4-disco/spi/spi-mems.c @@ -0,0 +1,304 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Chuck McManis + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library 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 Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* + * SPI Port example + */ + +#include +#include +#include +#include +#include "clock.h" +#include "console.h" + +/* + * Functions defined for accessing the SPI port 8 bits at a time + */ +uint16_t read_reg(int reg); +void write_reg(uint8_t reg, uint8_t value); +uint8_t read_xyz(int16_t vecs[3]); +void spi_init(void); + + +/* + * Chart of the various SPI ports (1 - 6) and where their pins can be: + + NSS SCK MISO MOSI + -------------- ------------------- ------------- --------------- + SPI1 PA4, PA15 PA5, PB3 PA6, PB4 PA7, PB5 + SPI2 PB9, PB12, PI0 PB10, PB13, PD3, PI1 PB14, PC2, PI2 PB15, PC3, PI3 + SPI3 PA15*, PA4* PB3*, PC10* PB4*, PC11* PB5*, PD6, PC12* + SPI4 PE4,PE11 PE2, PE12 PE5, PE13 PE6, PE14 + SPI5 PF6, PH5 PF7, PH6 PF8 PF9, PF11, PH7 + SPI6 PG8 PG13 PG12 PG14 + + Pin name with * is alternate function 6 otherwise use alternate function 5. + + * MEMS uses SPI5 - SCK (PF7), MISO (PF8), MOSI (PF9), + * MEMS CS* (PC1) -- GPIO + * MEMS INT1 = PA1, MEMS INT2 = PA2 + */ + +void put_status(char *m); + +/* + * put_status(char *) + * + * This is a helper function I wrote to watch the status register + * it decodes the bits and prints them on the console. Sometimes + * the SPI port comes up with the MODF flag set, you have to re-read + * the status port and re-write the control register to clear that. + */ +void put_status(char *m) { + uint16_t stmp; + + console_puts(m); + console_puts(" Status: "); + stmp = SPI_SR(SPI5); + if (stmp & SPI_SR_TXE) { + console_puts("TXE, "); + } + if (stmp & SPI_SR_RXNE) { + console_puts("RXNE, "); + } + if (stmp & SPI_SR_BSY) { + console_puts("BUSY, "); + } + if (stmp & SPI_SR_OVR) { + console_puts("OVERRUN, "); + } + if (stmp & SPI_SR_MODF) { + console_puts("MODE FAULT, "); + } + if (stmp & SPI_SR_CRCERR) { + console_puts("CRC, "); + } + if (stmp & SPI_SR_UDR) { + console_puts("UNDERRUN, "); + } + console_puts("\n"); +} + +/* + * read_reg(int reg) + * + * This reads the MEMs registers. The chip registers are 16 bits + * wide, but I read it as two 8 bit bytes. Originally I tried + * swapping between an 8 bit and 16 bit wide bus but that confused + * both my code and the chip after a while so this was found to + * be a more stable solution. + */ +uint16_t +read_reg(int reg) { + uint16_t d1, d2; + + d1 = 0x80 | (reg & 0x3f); // Read operation + /* Nominallly a register read is a 16 bit operation */ + gpio_clear(GPIOC, GPIO1); + spi_send(SPI5, d1); + d2 = spi_read(SPI5); + d2 <<= 8; + /* + * You have to send as many bits as you want to read + * so we send another 8 bits to get the rest of the + * register. + */ + spi_send(SPI5, 0); + d2 |= spi_read(SPI5); + gpio_set(GPIOC, GPIO1); + return d2; +} + +/* + * uint8_t status = read_xyz(int16_t []) + * + * This function exploits the fact that you can do a read + + * auto increment of the SPI registers. It starts at the + * address of the X register and reads 6 bytes. + * + * Then the status register is read and returned. + */ +uint8_t +read_xyz(int16_t vecs[3]) { + uint8_t buf[7]; + int i; + + gpio_clear(GPIOC, GPIO1); // CS* select + spi_send(SPI5, 0xc0 | 0x28); + (void) spi_read(SPI5); + for (i = 0; i < 6; i++) { + spi_send(SPI5, 0); + buf[i] = spi_read(SPI5); + } + gpio_set(GPIOC, GPIO1); // CS* deselect + vecs[0] = (buf[1] << 8 | buf[0]); + vecs[1] = (buf[3] << 8 | buf[2]); + vecs[3] = (buf[5] << 8 | buf[4]); + return read_reg(0x27); // Status register +} + +/* + * void write_reg(uint8_t register, uint8_t value) + * + * This code then writes into a register on the chip first + * selecting it and then writing to it. + */ +void +write_reg(uint8_t reg, uint8_t value) { + gpio_clear(GPIOC, GPIO1); // CS* select + spi_send(SPI5, reg); + (void) spi_read(SPI5); + spi_send(SPI5, value); + (void) spi_read(SPI5); + gpio_set(GPIOC, GPIO1); // CS* deselect + return; +} + +int print_decimal(int); + +/* + * int len = print_decimal(int value) + * + * Very simple routine to print an integer as a decimal + * number on the console. + */ +int +print_decimal(int num) { + int ndx = 0; + char buf[10]; + int len = 0; + char is_signed = 0; + + if (num < 0) { + is_signed++; + num = 0 - num; + } + buf[ndx++] = '\000'; + do { + buf[ndx++] = (num % 10) + '0'; + num = num / 10; + } while (num != 0); + ndx--; + if (is_signed != 0) { + console_putc('-'); + len++; + } + while (buf[ndx] != '\000') { + console_putc(buf[ndx--]); + len++; + } + return len; // number of characters printed +} + +char *axes[] = { "X: ", "Y: ", "Z: " }; + +/* + * This then is the actual bit of example. It initializes the + * SPI port, and then shows a continuous display of values on + * the console once you start it. Typing ^C will reset it. + */ +int main(void) { + int16_t vecs[3]; + int16_t baseline[3]; + int tmp, i; + int count; + uint32_t cr_tmp; + + clock_setup(); + console_setup(115200); + + /* Enable the GPIO ports whose pins we are using */ + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPFEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN); + + gpio_mode_setup(GPIOF, GPIO_MODE_AF, GPIO_PUPD_PULLDOWN, + GPIO7 | GPIO8 | GPIO9); + gpio_set_af(GPIOF, GPIO_AF5, GPIO7 | GPIO8 | GPIO9); + gpio_set_output_options(GPIOF, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, + GPIO7 | GPIO9); + + /* Chip select line */ + gpio_set(GPIOC, GPIO1); + gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO1); + + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SPI5EN); + + cr_tmp = SPI_CR1_BAUDRATE_FPCLK_DIV_8 |\ + SPI_CR1_MSTR |\ + SPI_CR1_SPE |\ + SPI_CR1_CPHA |\ + SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE ; + + put_status("\nBefore init: "); + SPI_CR2(SPI5) |= SPI_CR2_SSOE; + SPI_CR1(SPI5) = cr_tmp; + put_status("After init: "); + + + baseline[0] = 0; + baseline[1] = 0; + baseline[2] = 0; + console_puts("MEMS demo (new version):\n"); + console_puts("Press a key to read the registers\n"); + console_getc(1); + tmp = read_reg(0xf); + if (tmp != 0xD4) { + console_puts("Maybe this isn't a Gyroscope.\n"); + } + /* + * These parameters are sort of random, clearly I need + * set something. Based on the app note I reset the 'baseline' + * values after 100 samples. But don't see a lot of change + * when I move the board around. Z doesn't move at all but the + * temperature reading is correct and the ID code returned is + * as expected so the SPI code at least is working. + */ + write_reg(0x20, 0xcf); // Normal mode + write_reg(0x21, 0x07); // standard filters + write_reg(0x23, 0xb0); // 250 dps + tmp = (int) read_reg(0x26); + console_puts( "Temperature: "); + print_decimal(tmp); + console_puts( " C\n"); + + count = 0; + while (1) { + tmp = read_xyz(vecs); + for (i = 0; i < 3; i++) { + int pad; + console_puts( axes[i]); + tmp = vecs[i] - baseline[i]; + pad = print_decimal(tmp); + pad = 15 - pad; + while (pad--) { + console_puts( " "); + } + } + console_putc('\r'); + if (count == 100) { + baseline[0] = vecs[0]; + baseline[1] = vecs[1]; + baseline[2] = vecs[2]; + } else { + count++; + } + msleep(100); + } +}