Mercurial > ~darius > hgwebdir.cgi > stm32test
changeset 13:96c345d304af default tip
Add 1wire code.
1wire.c, 1wire.h and 1wire-config.h are copied avr-lib.
author | Daniel O'Connor <darius@dons.net.au> |
---|---|
date | Wed, 08 Feb 2012 10:37:22 +1030 |
parents | 093bc0c3b1cc |
children | |
files | 1wire-config.h 1wire.c 1wire.h BSDmakefile hw.c main.c |
diffstat | 6 files changed, 952 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/1wire-config.h Wed Feb 08 10:37:22 2012 +1030 @@ -0,0 +1,103 @@ +/* + * Example configuration header for 1-wire bus code. + * + * This is the user servicable stuff - how to do delays and how to + * frob the IO pins. + * + * Copyright (c) 2009 + * Daniel O'Connor <darius@dons.net.au>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * The configuration described here has the 1-wire IO on GPIOE3, + * with no pull down, nor VPP + */ + +#include "stm32f10x.h" /* GPIO* */ +#include "hw.h" /* For _usleep16() */ + +/* Fudge AVR stuff for ARM */ +#define PROGMEM +#define PSTR(x) x +#define pgm_read_byte(x) *(x) + +/* Init bus */ +#define OWBUSINIT() + +/* Set the port up to allow reading from the 1 wire bus */ +#define OWSETREAD() do { \ + GPIO_InitTypeDef GPIO_InitStructure; \ + \ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; \ + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; \ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; \ + GPIO_Init(GPIOE, &GPIO_InitStructure); \ +} while (0) + + +/* Read the 1-wire bus, non-inverting logic */ +#define OWREADBUS() (GPIO_ReadInputDataBit(GPIOE, GPIO_Pin_3) ? 1 : 0) + +/* Set the 1-wire bus to 0 + */ +#define OWSETBUSLOW() do { \ + GPIO_InitTypeDef GPIO_InitStructure; \ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; \ + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; \ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; \ + GPIO_Init(GPIOE, &GPIO_InitStructure); \ + GPIO_ResetBits(GPIOE, GPIO_Pin_3); \ +} while (0) + +/* Set the 1-wire bus to 1 + * Change to input and let the pull up do its job + */ +#define OWSETBUSHIGH() do { \ + GPIO_InitTypeDef GPIO_InitStructure; \ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; \ + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; \ + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; \ + GPIO_Init(GPIOE, &GPIO_InitStructure); \ +} while (0) + +#define OWDELAY_A _usleep16(6) /* 6 usec */ +#define OWDELAY_B _usleep16(64) /* 64 usec */ +#define OWDELAY_C _usleep16(60) /* 60 usec */ +#define OWDELAY_D _usleep16(10) /* 10 usec */ +#define OWDELAY_E _usleep16(9) /* 9 usec */ +#define OWDELAY_F _usleep16(55) /* 55 usec */ +#define OWDELAY_G /* 0 usec */ +#define OWDELAY_H _usleep16(480) /* 480 usec */ +#define OWDELAY_I _usleep16(70) /* 70 usec */ +#define OWDELAY_J _usleep16(410) /* 410 usec */ + +#ifdef OW_DEBUG +#define OWPUTS(x) puts(x) +#define OWPUTSP(x) puts(x) +#define OWPRINTFP(fmt, ...) printf(fmt, ## __VA_ARGS__) +#else +#define OWPUTS(x) +#define OWPUTSP(x) +#define OWPRINTFP(fmt, ...) +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/1wire.c Wed Feb 08 10:37:22 2012 +1030 @@ -0,0 +1,658 @@ +/* + * Various 1 wire routines + * Search routine is copied from the Dallas owpd library with mods + * available from here http://www.ibutton.com/software/1wire/wirekit.html + * + * $Id$ + * + * Copyright (c) 2004 + * Daniel O'Connor <darius@dons.net.au>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * No user servicable parts inside + * + * Modify 1wire-config.h + */ + +#include <stdio.h> +#include <stdint.h> +#include "1wire-config.h" +#include "1wire.h" + +static uint8_t OW_LastDevice = 0; +static uint8_t OW_LastDiscrepancy = 0; +static uint8_t OW_LastFamilyDiscrepancy = 0; + +const PROGMEM char *OWProgROM_Status[] = { + "OK", + "no HW support", + "Invalid params", + "module missing/broken" +}; + +/*----------------------------------------------------------------------------- + * Configure the IO port as we need + */ +void +OWInit(void) { + OWBUSINIT(); + OWSETBUSHIGH(); +} + +/*----------------------------------------------------------------------------- + * Generate a 1-Wire reset, return 0 if presence pulse was found, 1 if it + * wasn't, or 2 if the line appears to be being held low. + * + * (NOTE: Does not handle alarm presence from DS2404/DS1994) + */ +uint8_t +OWTouchReset(void) { + uint8_t i; + + OWDELAY_G; + + /* Check the bus isn't being held low (ie it's broken) Do it after + * the delay so we guarantee we don't see a slave from a previous + * comms attempt + */ +#if 1 + OWSETREAD(); + if(OWREADBUS() == 0) + return 2; +#endif + + OWSETBUSLOW(); + OWDELAY_H; + OWSETBUSHIGH(); + OWDELAY_I; + + OWSETREAD(); + i = OWREADBUS(); + + OWDELAY_J; + return(i); +} + +/*----------------------------------------------------------------------------- + * Send a 1-wire write bit. + */ +void +OWWriteBit(uint8_t bit) { + OWDELAY_I; + + if (bit) { + OWSETBUSLOW(); + OWDELAY_A; + OWSETBUSHIGH(); + OWDELAY_B; + } else { + OWSETBUSLOW(); + OWDELAY_C; + OWSETBUSHIGH(); + OWDELAY_D; + } +} + +/*----------------------------------------------------------------------------- + * Read a bit from the 1-wire bus and return it. + */ +uint8_t +OWReadBit(void) { + uint8_t i; + + OWDELAY_I; + + OWSETBUSLOW(); + OWDELAY_A; + OWSETBUSHIGH(); + OWDELAY_E; + OWSETREAD(); + i = OWREADBUS(); + OWDELAY_F; + return(i); +} + +/*----------------------------------------------------------------------------- + * Write a byte to the 1-wire bus + */ +void +OWWriteByte(uint8_t data) { + uint8_t i; + + /* Send LSB first */ + for (i = 0; i < 8; i++) { + OWWriteBit(data & 0x01); + data >>= 1; + } +} + +/*----------------------------------------------------------------------------- + * Read a byte from the 1-wire bus + */ +uint8_t +OWReadByte(void) { + int i, result = 0; + + for (i = 0; i < 8; i++) { + result >>= 1; + if (OWReadBit()) + result |= 0x80; + } + return(result); +} + +/*----------------------------------------------------------------------------- + * Write a 1-wire data byte and return the sampled result. + */ +uint8_t +OWTouchByte(uint8_t data) { + uint8_t i, result = 0; + + for (i = 0; i < 8; i++) { + result >>= 1; + + /* If sending a 1 then read a bit, otherwise write a 0 */ + if (data & 0x01) { + if (OWReadBit()) + result |= 0x80; + } else + OWWriteBit(0); + + data >>= 1; + } + + return(result); +} + +/*----------------------------------------------------------------------------- + * Write a block of bytes to the 1-wire bus and return the sampled result in + * the same buffer + */ +void +OWBlock(uint8_t *data, int len) { + int i; + + for (i = 0; i < len; i++) + data[i] = OWTouchByte(data[i]); +} + + +/*----------------------------------------------------------------------------- + * Send a 1 wire command to a device, or all if no ROM ID provided + */ +void +OWSendCmd(uint8_t *ROM, uint8_t cmd) { + uint8_t i; + + OWTouchReset(); + + if (ROM == NULL) + OWWriteByte(OW_SKIP_ROM_CMD); + else { + OWWriteByte(OW_MATCH_ROM_CMD); + for (i = 0; i < 8; i++) + OWWriteByte(ROM[i]); + } + OWWriteByte(cmd); +} + +/*----------------------------------------------------------------------------- + * Search algorithm from App note 187 (and 162) + * + * OWFirst/OWNext return.. + * 1 when something is found, + * 0 no more modules + * -1 if no presence pulse, + * -2 if bad CRC, + * -3 if bad wiring. + */ +uint8_t +OWFirst(uint8_t *ROM, uint8_t do_reset, uint8_t alarm_only) { + /* Reset state */ + OW_LastDiscrepancy = 0; + OW_LastDevice = 0; + OW_LastFamilyDiscrepancy = 0; + + /* Go looking */ + return (OWNext(ROM, do_reset, alarm_only)); +} + +/* Returns 1 when something is found, 0 if nothing left */ +uint8_t +OWNext(uint8_t *ROM, uint8_t do_reset, uint8_t alarm_only) { + uint8_t bit_test, search_direction, bit_number; + uint8_t last_zero, rom_byte_number, rom_byte_mask; + uint8_t lastcrc8, crcaccum; + int8_t next_result; + + /* Init for search */ + bit_number = 1; + last_zero = 0; + rom_byte_number = 0; + rom_byte_mask = 1; + next_result = OW_NOMODULES; + lastcrc8 = 0; + crcaccum = 0; + + /* if the last call was not the last one */ + if (!OW_LastDevice) { + /* check if reset first is requested */ + if (do_reset) { + /* reset the 1-wire + * if there are no parts on 1-wire, return 0 */ + OWPUTSP(PSTR("Resetting\r\n")); + switch (OWTouchReset()) { + case 0: + OWPUTSP(PSTR("Found device(s)\r\n")); + break; + + case 1: + /* reset the search */ + OW_LastDiscrepancy = 0; + OW_LastFamilyDiscrepancy = 0; + OWPUTSP(PSTR("No devices on bus\r\n")); + return OW_NOPRESENCE; + break; + + case 2: + /* reset the search */ + OW_LastDiscrepancy = 0; + OW_LastFamilyDiscrepancy = 0; + OWPUTSP(PSTR("Bus appears to be being held low\r\n")); + return OW_BADWIRE; + break; + + } + } + + /* If finding alarming devices issue a different command */ + if (alarm_only) + OWWriteByte(OW_SEARCH_ALRM_CMD); /* issue the alarming search command */ + else + OWWriteByte(OW_SEARCH_ROM_CMD); /* issue the search command */ + + /* pause before beginning the search */ + OWDELAY_I; + OWDELAY_I; + OWDELAY_I; + + /* loop to do the search */ + do { + /* read a bit and its compliment */ + bit_test = OWReadBit() << 1; + bit_test |= OWReadBit(); + + OWPRINTFP(PSTR("bit_test = %d\r\n"), bit_test); + + /* check for no devices on 1-wire */ + if (bit_test == 3) { + OWPRINTFP(PSTR("bit_test = %d\r\n"), bit_test); + return(OW_BADWIRE); + } + else { + /* all devices coupled have 0 or 1 */ + if (bit_test > 0) + search_direction = !(bit_test & 0x01); /* bit write value for search */ + else { + /* if this discrepancy is before the Last Discrepancy + * on a previous OWNext then pick the same as last time */ + if (bit_number < OW_LastDiscrepancy) + search_direction = ((ROM[rom_byte_number] & rom_byte_mask) > 0); + else + /* if equal to last pick 1, if not then pick 0 */ + search_direction = (bit_number == OW_LastDiscrepancy); + + /* if 0 was picked then record its position in LastZero */ + if (search_direction == 0) { + last_zero = bit_number; + + /* check for Last discrepancy in family */ + if (last_zero < 9) + OW_LastFamilyDiscrepancy = last_zero; + } + } + + /* set or clear the bit in the ROM byte rom_byte_number + * with mask rom_byte_mask */ + if (search_direction == 1) + ROM[rom_byte_number] |= rom_byte_mask; + else + ROM[rom_byte_number] &= ~rom_byte_mask; + + /* serial number search direction write bit */ + OWWriteBit(search_direction); + + /* increment the byte counter bit_number + * and shift the mask rom_byte_mask */ + bit_number++; + rom_byte_mask <<= 1; + + /* if the mask is 0 then go to new ROM byte rom_byte_number + * and reset mask */ + if (rom_byte_mask == 0) { + OWCRC(ROM[rom_byte_number], &crcaccum); /* accumulate the CRC */ + lastcrc8 = crcaccum; + + rom_byte_number++; + rom_byte_mask = 1; + } + } + } while (rom_byte_number < 8); /* loop until through all ROM bytes 0-7 */ + + /* if the search was successful then */ + if (!(bit_number < 65) || lastcrc8) { + if (lastcrc8) { + OWPRINTFP(PSTR("Bad CRC (%d)\r\n"), lastcrc8); + next_result = OW_BADCRC; + } else { + /* search successful so set LastDiscrepancy,LastDevice,next_result */ + OW_LastDiscrepancy = last_zero; + OW_LastDevice = (OW_LastDiscrepancy == 0); + OWPRINTFP(PSTR("Last device = %d\r\n"), OW_LastDevice); + next_result = OW_FOUND; + } + } + } + + /* if no device found then reset counters so next 'next' will be + * like a first */ + if (next_result != OW_FOUND || ROM[0] == 0) { + OW_LastDiscrepancy = 0; + OW_LastDevice = 0; + OW_LastFamilyDiscrepancy = 0; + } + + if (next_result == OW_FOUND && ROM[0] == 0x00) + next_result = OW_BADWIRE; + + return next_result; + +} + +uint8_t PROGMEM dscrc_table[] = { + 0, 94, 188, 226, 97, 63, 221, 131, 194, 156, 126, 32, 163, 253, 31, 65, + 157, 195, 33, 127, 252, 162, 64, 30, 95, 1, 227, 189, 62, 96, 130, 220, + 35, 125, 159, 193, 66, 28, 254, 160, 225, 191, 93, 3, 128, 222, 60, 98, + 190, 224, 2, 92, 223, 129, 99, 61, 124, 34, 192, 158, 29, 67, 161, 255, + 70, 24, 250, 164, 39, 121, 155, 197, 132, 218, 56, 102, 229, 187, 89, 7, + 219, 133,103, 57, 186, 228, 6, 88, 25, 71, 165, 251, 120, 38, 196, 154, + 101, 59, 217, 135, 4, 90, 184, 230, 167, 249, 27, 69, 198, 152, 122, 36, + 248, 166, 68, 26, 153, 199, 37, 123, 58, 100, 134, 216, 91, 5, 231, 185, + 140,210, 48, 110, 237, 179, 81, 15, 78, 16, 242, 172, 47, 113,147, 205, + 17, 79, 173, 243, 112, 46, 204, 146, 211,141, 111, 49, 178, 236, 14, 80, + 175, 241, 19, 77, 206, 144, 114, 44, 109, 51, 209, 143, 12, 82,176, 238, + 50, 108, 142, 208, 83, 13, 239, 177, 240, 174, 76, 18, 145, 207, 45, 115, + 202, 148, 118, 40, 171, 245, 23, 73, 8, 86, 180, 234, 105, 55, 213, 139, + 87, 9, 235, 181, 54, 104, 138, 212, 149, 203, 41, 119, 244, 170, 72, 22, + 233, 183, 85, 11, 136, 214, 52, 106, 43, 117, 151, 201, 74, 20, 246, 168, + 116, 42, 200, 150, 21, 75, 169, 247, 182, 232, 10, 84, 215, 137, 107, 53 +}; + +/*----------------------------------------------------------------------------- + * Update *crc based on the value of x + */ +void +OWCRC(uint8_t x, uint8_t *crc) { + *crc = pgm_read_byte(&dscrc_table[(*crc) ^ x]); +} + +/*----------------------------------------------------------------------------- + * Program a DS2502's memory + * + * Arguments + * ROM - ROM ID (or NULL to send SKIP_ROM) + * start - Start address (bytes) + * len - Length of data to write + * data - Data to write + * exact - If true, only accept exact matches for programming, + * otherwise only ensure the bits we requested were + * programmed [to 0] + * status - If true program status rather than memory + * + * Returns.. + * 0 if all is OK + * 1 if the programming is not possible + * 2 if the parameters were invalid + * 3 if the DS2502 didn't respond appropriately (also happens if the + * module doesn't exist) + */ +#if defined(OWSETVPPON) && defined(OWSETVPPOFF) +uint8_t +OWProgROM(uint8_t *ROM, uint8_t start, uint8_t len, uint8_t *data, uint8_t exact, uint8_t status) { + uint8_t crc, i, tmp; + + /* Stupid programmer detection */ + if (status) { + if (start + len > 3) + return(2); + } else { + if (start + len > 127) + return(2); + } + + if (len < 1) + return(2); + + OWDELAY_I; + if (OWTouchReset() != 0) { + cons_putsP(PSTR("No presence pulse\r\n")); + return(3); + } + + crc = 0; + + /* Send the command */ + if (status) { + OWSendCmd(ROM, OW_WRITE_STATUS); + OWCRC(OW_WRITE_STATUS, &crc); + } else { + OWSendCmd(ROM, OW_WRITE_MEMORY); + OWCRC(OW_WRITE_MEMORY, &crc); + } + + /* And the start address + * (2 bytes even though one would do) + */ + OWWriteByte(start); + OWCRC(start, &crc); + + OWWriteByte(0x00); + OWCRC(0x00, &crc); + + for (i = 0; i < len; i++) { + cons_putsP(PSTR("Programming ")); + cons_puts_hex(data[i]); + cons_putsP(PSTR(" to ")); + cons_puts_hex(start + i); + cons_putsP(PSTR("\r\n")); + + OWWriteByte(data[i]); + OWCRC(data[i], &crc); + + tmp = OWReadByte(); + + if (crc != tmp) { + cons_putsP(PSTR("CRC mismatch ")); + cons_puts_hex(crc); + cons_putsP(PSTR(" vs ")); + cons_puts_hex(tmp); + cons_putsP(PSTR("\r\n")); + + OWTouchReset(); + return(3); + } + + OWSETVPPON(); + OWDELAY_H; + OWSETVPPOFF(); + + tmp = OWReadByte(); + + /* Check the bits we turned off are off */ +/* + for (i = 0; i < 8; i++) + if (!(data[i] & 1 << i) && (tmp & 1 << i)) + return(-3); +*/ + if ((!data[i] & tmp) != 0) { + cons_putsP(PSTR("Readback mismatch ")); + cons_puts_hex(data[i]); + cons_putsP(PSTR(" vs ")); + cons_puts_hex(data[i]); + cons_putsP(PSTR("\r\n")); + + OWTouchReset(); + return(3); + } + + /* The DS2502 loads it's CRC register with the address of the + * next byte */ + crc = 0; + OWCRC(start + i + 1, &crc); + } + + return(0); +} +#else +uint8_t +OWProgROM(uint8_t *ROM __attribute((unused)), uint8_t start __attribute((unused)), uint8_t len __attribute((unused)), uint8_t *data __attribute((unused)), uint8_t exact __attribute((unused)), uint8_t status __attribute((unused))) { + return(1); +} +#endif + +/* + * OWGetTemp + * + * Get the temperature from a 1wire bus module + * + * Returns temperature in hundredths of a degree or OW_TEMP_xxx on + * error. + */ +int16_t +OWGetTemp(uint8_t *ROM) { + int8_t i; + uint8_t crc, buf[9]; + int16_t temp; + int16_t tfrac; + + if (ROM[0] != OW_FAMILY_TEMP) + return OW_TEMP_WRONG_FAM; + + OWSendCmd(ROM, OW_CONVERTT_CMD); + + i = 0; + + /* Wait for the conversion */ + while (OWReadBit() == 0) + i = 1; + + /* Check that we talked to a module and it did something */ + if (i == 0) { + return OW_TEMP_NO_ROM; + } + + OWSendCmd(ROM, OW_RD_SCR_CMD); + crc = 0; + for (i = 0; i < 8; i++) { + buf[i] = OWReadByte(); + OWCRC(buf[i], &crc); + } + buf[i] = OWReadByte(); + if (crc != buf[8]) + return OW_TEMP_CRC_ERR; + temp = buf[0]; + if (buf[1] & 0x80) + temp -= 256; + + /* Chop off 0.5 degree bit */ + temp >>= 1; + + /* Calulate the fractional remainder */ + tfrac = buf[7] - buf[6]; + + /* Work in 100'th of degreess to save on floats */ + tfrac *= (int16_t)100; + + /* Divide by count */ + tfrac /= buf[7]; + + /* Subtract 0.25 deg from temp */ + tfrac += 75; + if (tfrac < 100) + temp--; + else + tfrac -= 100; + + i = temp; + temp *= 100; + temp += tfrac; + + return(temp); +} + +/* + * OWTempStatusStr + * + * Return a string for each OW_TEMP_xxx error code + * + * shrt = 1 returns short strings + * + */ +const char * +OWTempStatusStr(int16_t val, uint8_t shrt) { + if (val > OW_TEMP_BADVAL) { + if (shrt) + return PSTR("OK"); + else + return PSTR("OK"); + } + + switch (val) { + case OW_TEMP_WRONG_FAM: + if (shrt) + return PSTR("WrFam"); + else + return PSTR("Wrong family"); + break; + case OW_TEMP_CRC_ERR: + if (shrt) + return PSTR("CRCErr"); + else + return PSTR("CRC Error"); + break; + case OW_TEMP_NO_ROM: + if (shrt) + return PSTR("NoROM"); + else + return PSTR("ROM did not reply"); + break; + default: + if (shrt) + return PSTR("???"); + else + return PSTR("Unknown error code"); + break; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/1wire.h Wed Feb 08 10:37:22 2012 +1030 @@ -0,0 +1,95 @@ +/* + * 1 wire header which defines functions and constants + * + * $Id$ + * + * Copyright (c) 2004 + * Daniel O'Connor <darius@dons.net.au>. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef PROGMEM +#define PROGMEM +#endif + +void OWInit(void); +uint8_t OWTouchReset(void); +void OWWriteBit(uint8_t bit); +uint8_t OWReadBit(void); +void OWWriteByte(uint8_t data); +uint8_t OWReadByte(void); +uint8_t OWTouchByte(uint8_t data); +void OWBlock(uint8_t *data, int len); +uint8_t OWFirst(uint8_t *ROM, uint8_t do_reset, uint8_t alarm_only); +uint8_t OWNext(uint8_t *ROM, uint8_t do_reset, uint8_t alarm_only); +void OWCRC(uint8_t x, uint8_t *crc); +void OWSendCmd(uint8_t *ROM, uint8_t cmd); +uint8_t OWProgROM(uint8_t *ROM, uint8_t start, uint8_t len, uint8_t *data, uint8_t exact, uint8_t status); +int16_t OWGetTemp(uint8_t *ROM); +const PROGMEM char *OWTempStatusStr(int16_t val, uint8_t shrt); +extern const PROGMEM char *OWProgROM_Status[]; + + +/* Return codes for OWFirst()/OWNext() */ +#define OW_BADWIRE -3 +#define OW_BADCRC -2 +#define OW_NOPRESENCE -1 +#define OW_NOMODULES 0 +#define OW_FOUND 1 + +/* General 1 wire commands */ +#define OW_OVRDRV_SKIP_CMD 0x3c +#define OW_SEARCH_ALRM_CMD 0xec +#define OW_SEARCH_ROM_CMD 0xf0 +#define OW_READ_ROM_CMD 0x33 +#define OW_MATCH_ROM_CMD 0x55 +#define OW_SKIP_ROM_CMD 0xcc + +/* DS1820 commands */ +#define OW_CONVERTT_CMD 0x44 +#define OW_RD_SCR_CMD 0xbe +#define OW_WR_SCR_CMD 0x4e +#define OW_CPY_SCR_CMD 0x48 +#define OW_RECALL_CMD 0xb8 +#define OW_RD_PSU_CMD 0xb4 + +/* DS2502 commands */ +#define OW_READ_MEMORY 0xf0 +#define OW_READ_STATUS 0xaa +#define OW_GEN_CRC 0xc3 +#define OW_WRITE_MEMORY 0x0f +#define OW_WRITE_STATUS 0x55 + +/* Family codes */ +#define OW_FAMILY_ROM 0x09 +#define OW_FAMILY_TEMP 0x10 + +/* Return codes for OWGetTemp */ +#define OW_TEMP_BADVAL -6000 +#define OW_TEMP_WRONG_FAM -6001 +#define OW_TEMP_CRC_ERR -6002 +#define OW_TEMP_NO_ROM -6003 + +/* Helpers for OWGetTemp's number system */ +#define GETWHOLE(x) ((x) / 100) +#define GETFRAC(x) abs((x) - (GETWHOLE(x) * 100))
--- a/BSDmakefile Mon Feb 06 23:55:53 2012 +1030 +++ b/BSDmakefile Wed Feb 08 10:37:22 2012 +1030 @@ -1,6 +1,7 @@ PROG= main -SRCS= comm.c \ +SRCS= 1wire.c \ + comm.c \ core_cm3.c \ delay.c \ flash.c \
--- a/hw.c Mon Feb 06 23:55:53 2012 +1030 +++ b/hw.c Wed Feb 08 10:37:22 2012 +1030 @@ -1,21 +1,24 @@ #include <stdint.h> #include <stdio.h> #include "stm32f10x.h" + +#include "1wire.h" #include "lcd.h" static void hw_port_cfg(void); /* Wait for cnt microseconds */ -void _usleep16(uint16_t cnt) { - TIM6->ARR = cnt; +void +_usleep16(uint16_t cnt) { + TIM6->ARR = cnt > 3 ? cnt - 3 : cnt; TIM_SetCounter(TIM6, 0); TIM_Cmd(TIM6, ENABLE); while ((TIM6->CR1 & TIM_CR1_CEN) != 0) ; - } -void hw_init(void) { +void +hw_init(void) { hw_port_cfg(); lcd_init(); lcd_setpwm(1000); @@ -279,17 +282,33 @@ /* Time Base configuration */ TIM_TimeBaseStructure.TIM_Period = 0; - TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 1000000) - 1; /* 1 MHz clock */ + TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 2 / 1000000) - 1; /* 1 MHz clock */ TIM_TimeBaseInit(TIM6, &TIM_TimeBaseStructure); TIM_Cmd(TIM6, DISABLE); - GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; + /* Setup for single pulse mode clear UDIS */ + TIM_SelectOnePulseMode(TIM6, TIM_OPMode_Single); + TIM_UpdateDisableConfig(TIM6, DISABLE); + + /* Setup GPIO for 1-wire */ + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOE, &GPIO_InitStructure); - TIM_SelectOnePulseMode(TIM6, TIM_OPMode_Single); - TIM_UpdateDisableConfig(TIM6, DISABLE); + OWInit(); +#if 0 + while (1) { + GPIO_SetBits(GPIOE, GPIO_Pin_2); + _usleep16(10); + GPIO_ResetBits(GPIOE, GPIO_Pin_2); + _usleep16(20); + GPIO_SetBits(GPIOE, GPIO_Pin_2); + _usleep16(30); + GPIO_ResetBits(GPIOE, GPIO_Pin_2); + _usleep16(100); + } +#endif }
--- a/main.c Mon Feb 06 23:55:53 2012 +1030 +++ b/main.c Wed Feb 08 10:37:22 2012 +1030 @@ -9,6 +9,7 @@ #include "stm32f10x.h" +#include "1wire.h" #include "comm.h" #include "delay.h" #include "flash.h" @@ -243,6 +244,72 @@ GPIO_ResetBits(GPIOE, GPIO_Pin_3); _usleep16(60000); } + } else if (!strncmp("rs", cmd.buf, 2)) { + printf("Reset got %d\r\n", OWTouchReset()); + } else if (!strncmp("sr", cmd.buf, 2)) { + uint8_t ROM[8]; + int8_t i; + + memset(ROM, 0, 8); + + i = OWFirst(ROM, 1, 0); + do { + switch (i) { + case OW_NOMODULES: + case OW_FOUND: + break; + + case OW_BADWIRE: + case OW_NOPRESENCE: + case OW_BADCRC: + default: + printf("Err %d\r\n", i); + break; + } + + if (i != OW_FOUND) + break; + + for (i = 0; i < 8; i++) + printf("%02x%s", ROM[i], i == 7 ? "\r\n" : ":"); + + i = OWNext(ROM, 1, 0); + } while (1); + } else if (!strncmp("rb", cmd.buf, 2)) { + printf("Read bit returned %d\r\n", OWReadBit()); + } else if (!strncmp("wb ", cmd.buf, 3)) { + x = atoi(cmd.buf + 3); + OWWriteBit(x); + printf("Wrote %d\r\n", x); + } else if (!strncasecmp(cmd.buf, "te ", 3)) { + uint8_t ROM[8]; + int16_t res; + + if (sscanf(cmd.buf, "te %hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", + &ROM[0], &ROM[1], &ROM[2], &ROM[3], + &ROM[4], &ROM[5], &ROM[6], &ROM[7]) != 8) { + printf("Unable to parse ROM ID\r\n"); + goto out; + } + + res = OWGetTemp(ROM); + switch (res) { + case OW_TEMP_WRONG_FAM: + printf("ROM specified isn't a temperature sensor\r\n"); + break; + + case OW_TEMP_CRC_ERR: + printf("CRC mismatch\r\n"); + break; + + case OW_TEMP_NO_ROM: + printf("No ROM found\r\n"); + break; + + default: + printf("%hd.%02hd\r\n", GETWHOLE(res), GETFRAC(res)); + break; + } } else if (!strncmp("zz", cmd.buf, 2)) { NVIC_SystemReset(); } else {