From 1025b8971dde3517c15107fcf0d8e9848ac3e03f Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Fri, 31 Jan 2014 05:27:13 +0000 Subject: [PATCH] Add initial hw1 stuff --- .gitignore | 5 + common.mk | 68 +++++++++++++ config.mk.example | 2 + hw1/acc.cc | 81 ++++++++++++++++ hw1/acc.h | 108 +++++++++++++++++++++ hw1/assignment.pdf | Bin 0 -> 73764 bytes hw1/mag.cc | 104 ++++++++++++++++++++ hw1/mag.h | 160 +++++++++++++++++++++++++++++++ hw1/makefile | 9 ++ hw1/mbed.cc | 47 +++++++++ hw1/tsi.cc | 231 +++++++++++++++++++++++++++++++++++++++++++++ hw1/tsi.h | 73 ++++++++++++++ 12 files changed, 888 insertions(+) create mode 100644 .gitignore create mode 100644 common.mk create mode 100644 config.mk.example create mode 100644 hw1/acc.cc create mode 100644 hw1/acc.h create mode 100644 hw1/assignment.pdf create mode 100644 hw1/mag.cc create mode 100644 hw1/mag.h create mode 100644 hw1/makefile create mode 100644 hw1/mbed.cc create mode 100644 hw1/tsi.cc create mode 100644 hw1/tsi.h diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8764137 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +*.bin +*.elf +*.o +*~ +config.mk diff --git a/common.mk b/common.mk new file mode 100644 index 0000000..710c645 --- /dev/null +++ b/common.mk @@ -0,0 +1,68 @@ +# Settings +GDB ?= arm-none-eabi-gdb +GAS ?= arm-none-eabi-as +GCC ?= arm-none-eabi-gcc +GXX ?= arm-none-eabi-g++ +GLD ?= arm-none-eabi-gcc +OBJCOPY ?= arm-none-eabi-objcopy + +CFLAGS ?= -Wall -Os -g --std=gnu99 +CXXFLAGS ?= -Wall -Os -g --std=gnu++98 + +# Cross compiler flags +CPPFLAGS += -I$(MBED) -I$(MBED)/TARGET_KL46Z + +CFLAGS += -mthumb -mcpu=cortex-m0plus +CXXFLAGS += -mthumb -mcpu=cortex-m0plus -fno-exceptions + +LDFLAGS += --specs=nano.specs -Wl,--gc-sections \ + -T$(MBED)/TARGET_KL46Z/TOOLCHAIN_GCC_ARM/MKL46Z4.ld \ + -L$(MBED)/TARGET_KL46Z/TOOLCHAIN_GCC_ARM \ + -Wl,--start-group -lmbed -lstartup -lio -lc_s -Wl,--end-group + +# Targets +all: $(PROG).bin + +info: all + @echo "LS $(PROG).bin $(PROG).elf" + @ls -lh $(PROG).bin $(PROG).elf + +install: all + @echo "INST $(PROG).bin" + @if [ -b /dev/sdb ]; then \ + mount /mnt/usb; \ + cp $(PROG).bin /mnt/usb; \ + umount /mnt/usb; \ + else \ + echo Error: No USB found; \ + fi + +gdb: all + $(GDB) -ex 'target remote localhost:3333' $(PROG).elf + +openocd: all + openocd -c 'adapter_khz 5000' \ + -c 'gdb_memory_map disable' \ + -s /usr/share/openocd/scripts \ + -f board/frdm-kl46z.cfg + +clean: + @echo "RM $(PROG).bin $(PROG).elf $(OBJS)" + @rm -f $(PROG).bin $(PROG).elf $(OBJS) + +# Rules +%.o: %.c makefile ../common.mk ../config.mk + @echo "CC $<" + @$(GCC) $(CFLAGS) $(CPPFLAGS) -c -o $@ $< + +%.o: %.cc makefile ../common.mk ../config.mk + @echo "CXX $<" + @$(GXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $< + +$(PROG).elf: $(OBJS) + @echo "LD $+" + @$(GLD) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +$(PROG).bin: $(PROG).elf + @echo "BIN $+" + @$(OBJCOPY) -O binary $< $@ diff --git a/config.mk.example b/config.mk.example new file mode 100644 index 0000000..3c9ab5a --- /dev/null +++ b/config.mk.example @@ -0,0 +1,2 @@ +PATH := $(PATH):/home/andy/class/csm213a/arm/bin +MBED := /home/andy/class/csm213a/mbed/build/mbed diff --git a/hw1/acc.cc b/hw1/acc.cc new file mode 100644 index 0000000..f398675 --- /dev/null +++ b/hw1/acc.cc @@ -0,0 +1,81 @@ +/* Copyright (c) 2010-2011 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include "acc.h" + +#define REG_WHO_AM_I 0x0D +#define REG_CTRL_REG_1 0x2A +#define REG_OUT_X_MSB 0x01 +#define REG_OUT_Y_MSB 0x03 +#define REG_OUT_Z_MSB 0x05 + +#define UINT14_MAX 16383 + +MMA8451Q::MMA8451Q(PinName sda, PinName scl, int addr) : m_i2c(sda, scl), m_addr(addr) { + // activate the peripheral + uint8_t data[2] = {REG_CTRL_REG_1, 0x01}; + writeRegs(data, 2); +} + +MMA8451Q::~MMA8451Q() { } + +uint8_t MMA8451Q::getWhoAmI() { + uint8_t who_am_i = 0; + readRegs(REG_WHO_AM_I, &who_am_i, 1); + return who_am_i; +} + +int16_t MMA8451Q::getAccX() { + return getAccAxis(REG_OUT_X_MSB); +} + +int16_t MMA8451Q::getAccY() { + return getAccAxis(REG_OUT_Y_MSB); +} + +int16_t MMA8451Q::getAccZ() { + return getAccAxis(REG_OUT_Z_MSB); +} + +void MMA8451Q::getAccAllAxis(int16_t * res) { + res[0] = getAccX(); + res[1] = getAccY(); + res[2] = getAccZ(); +} + +int16_t MMA8451Q::getAccAxis(uint8_t addr) { + int16_t acc; + uint8_t res[2]; + readRegs(addr, res, 2); + + acc = (res[0] << 6) | (res[1] >> 2); + if (acc > UINT14_MAX/2) + acc -= UINT14_MAX; + + return acc; +} + +void MMA8451Q::readRegs(int addr, uint8_t * data, int len) { + char t[1] = {(char)addr}; + m_i2c.write(m_addr, t, 1, true); + m_i2c.read(m_addr, (char *)data, len); +} + +void MMA8451Q::writeRegs(uint8_t * data, int len) { + m_i2c.write(m_addr, (char *)data, len); +} diff --git a/hw1/acc.h b/hw1/acc.h new file mode 100644 index 0000000..1b22268 --- /dev/null +++ b/hw1/acc.h @@ -0,0 +1,108 @@ +/* Copyright (c) 2010-2011 mbed.org, MIT License +* +* Permission is hereby granted, free of charge, to any person obtaining a copy of this software +* and associated documentation files (the "Software"), to deal in the Software without +* restriction, including without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the +* Software is furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in all copies or +* substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING +* BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#ifndef MMA8451Q_H +#define MMA8451Q_H + +#include "mbed.h" + +/** +* MMA8451Q accelerometer example +* #include "mbed.h" +* #include "MMA8451Q.h" +* +* #define MMA8451_I2C_ADDRESS (0x1d<<1) +* +* int main(void) { +* DigitalOut led(LED_GREEN); +* MMA8451Q acc(P_E25, P_E24, MMA8451_I2C_ADDRESS); +* printf("WHO AM I: 0x%2X\r\n", acc.getWhoAmI()); +* +* while (true) { +* printf("-----------\r\n"); +* printf("acc_x: %d\r\n", acc.getAccX()); +* printf("acc_y: %d\r\n", acc.getAccY()); +* printf("acc_z: %d\r\n", acc.getAccZ()); +* +* wait(1); +* led = !led; +* } +* } +*/ +class MMA8451Q +{ +public: + /** + * MMA8451Q constructor + * + * @param sda SDA pin + * @param sdl SCL pin + * @param addr addr of the I2C peripheral + */ + MMA8451Q(PinName sda, PinName scl, int addr); + + /** + * MMA8451Q destructor + */ + ~MMA8451Q(); + + /** + * Get the value of the WHO_AM_I register + * + * @returns WHO_AM_I value + */ + uint8_t getWhoAmI(); + + /** + * Get X axis acceleration + * + * @returns X axis acceleration + */ + int16_t getAccX(); + + /** + * Get Y axis acceleration + * + * @returns Y axis acceleration + */ + int16_t getAccY(); + + /** + * Get Z axis acceleration + * + * @returns Z axis acceleration + */ + int16_t getAccZ(); + + /** + * Get XYZ axis acceleration + * + * @param res array where acceleration data will be stored + */ + void getAccAllAxis(int16_t * res); + +private: + I2C m_i2c; + int m_addr; + void readRegs(int addr, uint8_t * data, int len); + void writeRegs(uint8_t * data, int len); + int16_t getAccAxis(uint8_t addr); + +}; + +#endif diff --git a/hw1/assignment.pdf b/hw1/assignment.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e581b1383d1def4b693f8c7201ebe0e8e66a91f1 GIT binary patch literal 73764 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 z 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 literal 0 HcmV?d00001 diff --git a/hw1/mag.cc b/hw1/mag.cc new file mode 100644 index 0000000..a379bf2 --- /dev/null +++ b/hw1/mag.cc @@ -0,0 +1,104 @@ +#include "mbed.h" +#include "mag.h" + +/****************************************************************************** + * Constructors + ******************************************************************************/ +MAG3110::MAG3110(PinName sda, PinName scl, int addr): _i2c(sda, scl), + _i2c_address(addr), _pc(NULL), _debug(false) +{ + begin(); +} + +MAG3110::MAG3110(PinName sda, PinName scl, int addr, Serial *pc): _i2c(sda, scl), + _i2c_address(addr), _pc(pc), _debug(true) +{ + begin(); +} + +void MAG3110::begin() +{ + char cmd[2]; + + cmd[0] = MAG_CTRL_REG2; + cmd[1] = 0x80; + _i2c.write(_i2c_address, cmd, 2); + + cmd[0] = MAG_CTRL_REG1; + cmd[1] = MAG_3110_SAMPLE80+MAG_3110_OVERSAMPLE2+MAG_3110_ACTIVE; + _i2c.write(_i2c_address, cmd, 2); + + // No adjustment initially + _avgX = 0; + _avgY = 0; +} + +// Read a single byte form 8 bit register, return as int +int MAG3110::readReg(char regAddr) +{ + char cmd[1]; + + cmd[0] = regAddr; + _i2c.write(_i2c_address, cmd, 1); + + cmd[0] = 0x00; + _i2c.read(_i2c_address, cmd, 1); + return (int)( cmd[0]); +} + + +// read a register per, pass first reg value, reading 2 bytes increments register +// Reads MSB first then LSB +int MAG3110::readVal(char regAddr) +{ + char cmd[2]; + + cmd[0] = regAddr; + _i2c.write(_i2c_address, cmd, 1); + + cmd[0] = 0x00; + cmd[1] = 0x00; + _i2c.read(_i2c_address, cmd, 2); + return (int)( (cmd[1]|(cmd[0] << 8))); //concatenate the MSB and LSB +} + + +float MAG3110::getHeading() +{ + int xVal = readVal(MAG_OUT_X_MSB); + int yVal = readVal(MAG_OUT_Y_MSB); + return (atan2((double)(yVal - _avgY),(double)(xVal - _avgX)))*180/PI; +} + +void MAG3110::getValues(int *xVal, int *yVal, int *zVal) +{ + *xVal = readVal(MAG_OUT_X_MSB); + *yVal = readVal(MAG_OUT_Y_MSB); + *zVal = readVal(MAG_OUT_Z_MSB); +} + +int16_t MAG3110::getMagX() +{ + return readVal(MAG_OUT_X_MSB); +} + +int16_t MAG3110::getMagY() +{ + return readVal(MAG_OUT_Y_MSB); +} + +int16_t MAG3110::getMagZ() +{ + return readVal(MAG_OUT_Z_MSB); +} + +void MAG3110::setCalibration(int minX, int maxX, int minY, int maxY ) +{ + _avgX=(maxX+minX)/2; + _avgY=(maxY+minY)/2; +} + + + + + diff --git a/hw1/mag.h b/hw1/mag.h new file mode 100644 index 0000000..7ddbde6 --- /dev/null +++ b/hw1/mag.h @@ -0,0 +1,160 @@ +/* + * MAG3110 Sensor Library for mbed + * TODO: Add proper header + */ + +#ifndef MAG3110_H +#define MAG3110_H + +#include "mbed.h" + +#define PI 3.14159265359 + +// define registers +#define MAG_DR_STATUS 0x00 +#define MAG_OUT_X_MSB 0x01 +#define MAG_OUT_X_LSB 0x02 +#define MAG_OUT_Y_MSB 0x03 +#define MAG_OUT_Y_LSB 0x04 +#define MAG_OUT_Z_MSB 0x05 +#define MAG_OUT_Z_LSB 0x06 +#define MAG_WHO_AM_I 0x07 +#define MAG_SYSMOD 0x08 +#define MAG_OFF_X_MSB 0x09 +#define MAG_OFF_X_LSB 0x0A +#define MAG_OFF_Y_MSB 0x0B +#define MAG_OFF_Y_LSB 0x0C +#define MAG_OFF_Z_MSB 0x0D +#define MAG_OFF_Z_LSB 0x0E +#define MAG_DIE_TEMP 0x0F +#define MAG_CTRL_REG1 0x10 +#define MAG_CTRL_REG2 0x11 + +// what should WHO_AM_I return? +#define MAG_3110_WHO_AM_I_VALUE 0xC4 + + +// Fields in registers +// CTRL_REG1: dr2,dr1,dr0 os1,os0 fr tm ac + +// Sampling rate from 80Hz down to 0.625Hz +#define MAG_3110_SAMPLE80 0 +#define MAG_3110_SAMPLE40 0x20 +#define MAG_3110_SAMPLE20 0x40 +#define MAG_3110_SAMPLE10 0x60 +#define MAG_3110_SAMPLE5 0x80 +#define MAG_3110_SAMPLE2_5 0xA0 +#define MAG_3110_SAMPLE1_25 0xC0 +#define MAG_3110_SAMPLE0_625 0xE0 + +// How many samples to average (lowers data rate) +#define MAG_3110_OVERSAMPLE1 0 +#define MAG_3110_OVERSAMPLE2 0x08 +#define MAG_3110_OVERSAMPLE3 0x10 +#define MAG_3110_OVERSAMPLE4 0x18 + +// read only 1 byte per axis +#define MAG_3110_FASTREAD 0x04 +// do one measurement (even if in standby mode) +#define MAG_3110_TRIGGER 0x02 +// put in active mode +#define MAG_3110_ACTIVE 0x01 + +// CTRL_REG2: AUTO_MRST_EN _ RAW MAG_RST _ _ _ _ _ +// reset sensor after each reading +#define MAG_3110_AUTO_MRST_EN 0x80 +// don't subtract user offsets +#define MAG_3110_RAW 0x20 +// reset magnetic sensor after too-large field +#define MAG_3110_MAG_RST 0x10 + +// DR_STATUS Register ZYXOW ZOW YOW XOW ZYXDR ZDR YDR XDR +#define MAG_3110_ZYXDR 0x08 + +/** + * MAG3110 Class to read X/Y/Z data from the magentometer + * + */ +class MAG3110 +{ +public: + /** + * Main constructor + * @param sda SDA pin + * @param sdl SCL pin + * @param addr addr of the I2C peripheral + */ + MAG3110(PinName sda, PinName scl, int addr); + /** + * Debug version of constructor + * @param sda SDA pin + * @param sdl SCL pin + * @param addr Address of the I2C peripheral + * @param pc Serial object to output debug messages + */ + MAG3110(PinName sda, PinName scl, int addr, Serial *pc); //pass serial for debug + /** + * Setup the Magnetometer + * + */ + void begin(); + /** + * Read a register, return its value as int + * @param regAddr The address to read + * @return value in register + */ + int readReg(char regAddr); + /** + * Read a value from a pair of registers, return as int + * @param regAddr The address to read + * @return Value from 2 consecutive registers + */ + int readVal(char regAddr); + /** + * Calculate the heading + * @return heading in degrees + */ + float getHeading(); + /** + * Perform a read on the X, Y and Z values. + * @param xVal Pointer to X value + * @param yVal Pointer to Y value + * @param zVal Pointer to Z value + */ + void getValues(int *xVal, int *yVal, int *zVal); + /** + * Set the calibration parameters if required. + * @param minX Minimum value for X range + * @param maxX Maximum value for X range + * @param minY Minimum value for Y range + * @param maxY maximum value for Y range + */ + void setCalibration(int minX, int maxX, int minY, int maxY); + /** + * Get X axis magnetism + * + * @returns X axis magnetism + */ + int16_t getMagX(); + /** + * Get Y axis magnetism + * + * @returns Y axis magnetism + */ + int16_t getMagY(); + /** + * Get Z axis magnetism + * + * @returns Z axis magnetism + */ + int16_t getMagZ(); + +private: + I2C _i2c; + int _i2c_address; + Serial *_pc; + bool _debug; + int _avgX, _avgY; + +}; +#endif diff --git a/hw1/makefile b/hw1/makefile new file mode 100644 index 0000000..9a4e195 --- /dev/null +++ b/hw1/makefile @@ -0,0 +1,9 @@ +PROG = mbed +OBJS = mbed.o tsi.o acc.o mag.o + +LDFLAGS = -lm + +default: info install + +-include ../config.mk +-include ../common.mk diff --git a/hw1/mbed.cc b/hw1/mbed.cc new file mode 100644 index 0000000..645d6da --- /dev/null +++ b/hw1/mbed.cc @@ -0,0 +1,47 @@ +#include "mbed.h" +#include "tsi.h" +#include "acc.h" +#include "mag.h" + +/* Sensors: + * accel [x,y,z] + * compas + * light + * slider + * a2d[6] + */ + +#define ACC_ADDR (0x1D<<1) +#define MAG_ADDR (0x1D) // FIXME + +DigitalOut led1(LED1); +DigitalOut led2(LED2); +MMA8451Q acc(PTE25, PTE24, ACC_ADDR); +MAG3110 mag(PTE25, PTE24, MAG_ADDR); +TSISensor tsi; + +static int state = 0; + +int main(int argc, char **argv) +{ + printf("Starting...\r\n"); + while (1) { + int chr = getchar(); + putchar(chr); + + printf("tsi: [%d]\r\n", + tsi.readDistance()); + printf("acc: [%d,%d,%d]\r\n", + acc.getAccX(), + acc.getAccY(), + acc.getAccZ()); + printf("mag: [%d,%d,%d]\r\n", + mag.getMagX(), + mag.getMagY(), + mag.getMagZ()); + + led2 = state; + state ^= 1; + } + return 0; +} diff --git a/hw1/tsi.cc b/hw1/tsi.cc new file mode 100644 index 0000000..e83775e --- /dev/null +++ b/hw1/tsi.cc @@ -0,0 +1,231 @@ +/* Freescale Semiconductor Inc. + * (c) Copyright 2004-2005 Freescale Semiconductor, Inc. + * (c) Copyright 2001-2004 Motorola, Inc. + * + * mbed Microcontroller Library + * (c) Copyright 2009-2012 ARM Limited. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#include "mbed.h" +#include "tsi.h" + +#define NO_TOUCH 0 +#define SLIDER_LENGTH 40 //LENGTH in mm +#define TOTAL_ELECTRODE 2 + +#define TSI0a 0 +#define TSI1 1 +#define TSI2 2 +#define TSI3 3 +#define TSI4 4 +#define TSI5 5 +#define TSI6 6 +#define TSI7 7 +#define TSI8 8 +#define TSI9 9 +#define TSI10 10 +#define TSI11 11 +#define TSI12 12 +#define TSI13 13 +#define TSI14 14 +#define TSI15 15 + +/*Chose the correct TSI channel for the electrode number*/ +#define ELECTRODE0 TSI9 +#define ELECTRODE1 TSI10 +#define ELECTRODE2 TSI0a +#define ELECTRODE3 TSI1 +#define ELECTRODE4 TSI2 +#define ELECTRODE5 TSI3 +#define ELECTRODE6 TSI4 +#define ELECTRODE7 TSI5 +#define ELECTRODE8 TSI6 +#define ELECTRODE9 TSI7 +#define ELECTRODE10 TSI8 +#define ELECTRODE11 TSI11 +#define ELECTRODE12 TSI12 +#define ELECTRODE13 TSI13 +#define ELECTRODE14 TSI14 +#define ELECTRODE15 TSI15 + +#define THRESHOLD0 100 +#define THRESHOLD1 100 +#define THRESHOLD2 100 +#define THRESHOLD3 100 +#define THRESHOLD4 100 +#define THRESHOLD5 100 +#define THRESHOLD6 100 +#define THRESHOLD7 100 +#define THRESHOLD8 100 +#define THRESHOLD9 100 +#define THRESHOLD10 100 +#define THRESHOLD11 100 +#define THRESHOLD12 100 +#define THRESHOLD13 100 +#define THRESHOLD14 100 +#define THRESHOLD15 100 + +static uint8_t total_electrode = TOTAL_ELECTRODE; +static uint8_t elec_array[16]={ELECTRODE0,ELECTRODE1,ELECTRODE2,ELECTRODE3,ELECTRODE4,ELECTRODE5, + ELECTRODE6,ELECTRODE7,ELECTRODE8,ELECTRODE9,ELECTRODE10,ELECTRODE11, + ELECTRODE12,ELECTRODE13,ELECTRODE14,ELECTRODE15}; +static uint16_t gu16TSICount[16]; +static uint16_t gu16Baseline[16]; +static uint16_t gu16Threshold[16]={THRESHOLD0,THRESHOLD1,THRESHOLD2,THRESHOLD3,THRESHOLD4,THRESHOLD5, + THRESHOLD6,THRESHOLD7,THRESHOLD8,THRESHOLD9,THRESHOLD10,THRESHOLD11, + THRESHOLD12,THRESHOLD13,THRESHOLD14,THRESHOLD15}; +static uint16_t gu16Delta[16]; +static uint8_t ongoing_elec; +static uint8_t end_flag = 1; + +static uint8_t SliderPercentegePosition[2] = {NO_TOUCH,NO_TOUCH}; +static uint8_t SliderDistancePosition[2] = {NO_TOUCH,NO_TOUCH}; +static uint32_t AbsolutePercentegePosition = NO_TOUCH; +static uint32_t AbsoluteDistancePosition = NO_TOUCH; + +static void tsi_irq(); + +TSISensor::TSISensor() { + SIM->SCGC5 |= SIM_SCGC5_PORTB_MASK; + SIM->SCGC5 |= SIM_SCGC5_TSI_MASK; + + TSI0->GENCS |= (TSI_GENCS_ESOR_MASK + | TSI_GENCS_MODE(0) + | TSI_GENCS_REFCHRG(4) + | TSI_GENCS_DVOLT(0) + | TSI_GENCS_EXTCHRG(7) + | TSI_GENCS_PS(4) + | TSI_GENCS_NSCN(11) + | TSI_GENCS_TSIIEN_MASK + | TSI_GENCS_STPE_MASK + ); + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; + + NVIC_SetVector(TSI0_IRQn, (uint32_t)&tsi_irq); + NVIC_EnableIRQ(TSI0_IRQn); + + selfCalibration(); +} + + +void TSISensor::selfCalibration(void) +{ + unsigned char cnt; + unsigned char trigger_backup; + + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; // Clear End of Scan Flag + TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK; // Disable TSI module + + if(TSI0->GENCS & TSI_GENCS_STM_MASK) // Back-up TSI Trigger mode from Application + trigger_backup = 1; + else + trigger_backup = 0; + + TSI0->GENCS &= ~TSI_GENCS_STM_MASK; // Use SW trigger + TSI0->GENCS &= ~TSI_GENCS_TSIIEN_MASK; // Enable TSI interrupts + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; // Enable TSI module + + for(cnt=0; cnt < total_electrode; cnt++) // Get Counts when Electrode not pressed + { + TSI0->DATA = ((elec_array[cnt] << TSI_DATA_TSICH_SHIFT) ); + TSI0->DATA |= TSI_DATA_SWTS_MASK; + while(!(TSI0->GENCS & TSI_GENCS_EOSF_MASK)); + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; + gu16Baseline[cnt] = (TSI0->DATA & TSI_DATA_TSICNT_MASK); + } + + TSI0->GENCS &= ~TSI_GENCS_TSIEN_MASK; // Disable TSI module + TSI0->GENCS |= TSI_GENCS_TSIIEN_MASK; // Enale TSI interrupt + if(trigger_backup) // Restore trigger mode + TSI0->GENCS |= TSI_GENCS_STM_MASK; + else + TSI0->GENCS &= ~TSI_GENCS_STM_MASK; + + TSI0->GENCS |= TSI_GENCS_TSIEN_MASK; // Enable TSI module + + TSI0->DATA = ((elec_array[0]<DATA |= TSI_DATA_SWTS_MASK; +} + + +void TSISensor::sliderRead(void ) { + if(end_flag) { + end_flag = 0; + if((gu16Delta[0] > gu16Threshold[0])||(gu16Delta[1] > gu16Threshold[1])) { + SliderPercentegePosition[0] = (gu16Delta[0]*100)/(gu16Delta[0]+gu16Delta[1]); + SliderPercentegePosition[1] = (gu16Delta[1]*100)/(gu16Delta[0]+gu16Delta[1]); + SliderDistancePosition[0] = (SliderPercentegePosition[0]* SLIDER_LENGTH)/100; + SliderDistancePosition[1] = (SliderPercentegePosition[1]* SLIDER_LENGTH)/100; + AbsolutePercentegePosition = ((100 - SliderPercentegePosition[0]) + SliderPercentegePosition[1])/2; + AbsoluteDistancePosition = ((SLIDER_LENGTH - SliderDistancePosition[0]) + SliderDistancePosition[1])/2; + } else { + SliderPercentegePosition[0] = NO_TOUCH; + SliderPercentegePosition[1] = NO_TOUCH; + SliderDistancePosition[0] = NO_TOUCH; + SliderDistancePosition[1] = NO_TOUCH; + AbsolutePercentegePosition = NO_TOUCH; + AbsoluteDistancePosition = NO_TOUCH; + } + } +} + +float TSISensor::readPercentage() { + sliderRead(); + return (float)AbsolutePercentegePosition/100.0; +} + +uint8_t TSISensor::readDistance() { + sliderRead(); + return AbsoluteDistancePosition; +} + + +static void changeElectrode(void) +{ + int16_t u16temp_delta; + + gu16TSICount[ongoing_elec] = (TSI0->DATA & TSI_DATA_TSICNT_MASK); // Save Counts for current electrode + u16temp_delta = gu16TSICount[ongoing_elec] - gu16Baseline[ongoing_elec]; // Obtains Counts Delta from callibration reference + if(u16temp_delta < 0) + gu16Delta[ongoing_elec] = 0; + else + gu16Delta[ongoing_elec] = u16temp_delta; + + //Change Electrode to Scan + if(total_electrode > 1) + { + if((total_electrode-1) > ongoing_elec) + ongoing_elec++; + else + ongoing_elec = 0; + + TSI0->DATA = ((elec_array[ongoing_elec]<DATA |= TSI_DATA_SWTS_MASK; + } +} + + +void tsi_irq(void) +{ + end_flag = 1; + TSI0->GENCS |= TSI_GENCS_EOSF_MASK; // Clear End of Scan Flag + changeElectrode(); +} + diff --git a/hw1/tsi.h b/hw1/tsi.h new file mode 100644 index 0000000..1ac547b --- /dev/null +++ b/hw1/tsi.h @@ -0,0 +1,73 @@ +/* Freescale Semiconductor Inc. + * (c) Copyright 2004-2005 Freescale Semiconductor, Inc. + * (c) Copyright 2001-2004 Motorola, Inc. + * + * mbed Microcontroller Library + * (c) Copyright 2009-2012 ARM Limited. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software + * and associated documentation files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or + * substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +#ifndef TSISENSOR_H +#define TSISENSOR_H + +/** +* TSISensor example +* +* @code +* #include "mbed.h" +* #include "TSISensor.h" +* +* int main(void) { +* DigitalOut led(LED_GREEN); +* TSISensor tsi; +* +* while (true) { +* printf("slider percentage: %f%\r\n", tsi.readPercentage()); +* printf("slider distance: %dmm\r\n", tsi.readDistance()); +* wait(1); +* led = !led; +* } +* } +* @endcode +*/ +class TSISensor { +public: + /** + * Initialize the TSI Touch Sensor + */ + TSISensor(); + + /** + * Read Touch Sensor percentage value + * + * @returns percentage value between [0 ... 1] + */ + float readPercentage(); + + /** + * Read Touch Sensor distance + * + * @returns distance in mm. The value is between [0 ... 40] + */ + uint8_t readDistance(); + +private: + void sliderRead(void); + void selfCalibration(void); +}; + +#endif -- 2.43.2