Mercurial > ~darius > hgwebdir.cgi > avr
changeset 0:ffeab3c04e83
Initial revision
author | darius |
---|---|
date | Sun, 11 Jul 2004 00:45:50 +0930 |
parents | |
children | 83c649cc59af 288d801a47ff |
files | 1wire.c 1wire.h Makefile testavr.c |
diffstat | 4 files changed, 897 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/1wire.c Sun Jul 11 00:45:50 2004 +0930 @@ -0,0 +1,530 @@ +/* + * Various 1 wire routines + * Search routine is copied from the Dallas owpd library with mods. + * + * 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. + */ + +#include <stdio.h> +#include <avr/io.h> +#include <avr/pgmspace.h> + +#include "1wire.h" + +void uart_putsP(const char *addr); +void uart_puts(const char *addr); +void uart_getc(); +int uart_putc(char c); + +static uint8_t OW_LastDevice = 0; +static uint8_t OW_LastDiscrepancy = 0; +static uint8_t OW_LastFamilyDiscrepancy = 0; + +static void +OWdelay(void) { + asm volatile ( + "ldi r21, 50\n\t" + "_OWdelay:\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "dec r21\n\t" + "brne _OWdelay\n\t" + ::: "r21"); +} + +/*----------------------------------------------------------------------------- + * Generate a 1-Wire reset, return 1 if no presence detect was found, + * return 0 otherwise. + * (NOTE: Does not handle alarm presence from DS2404/DS1994) + */ +int +OWTouchReset(void) { + uint8_t result; + + asm volatile ( + /* Delay G (0 usec) */ + "\n\t" + /* Drive bus low */ + "cbi %[out], %[opin]\n\t" + "sbi %[ddr], %[opin]\n\t" + /* Delay H (480 usec) */ + "ldi r21, 120\n\t" + "loopH:\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopH\n\t" + /* Release bus */ + "cbi %[ddr], %[opin]\n\t" + /* Delay I (70 usec) */ + "ldi r21, 35\n\t" + "loopI:\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopI\n\t" + /* Sample for presense */ + "ldi %[result], 0\n\t" + "sbi %[ddr], 1\n\t" + "sbi %[out], 1\n\t" + /* 1 == no presence */ + "sbic %[in], %[ipin]\n\t" + "ldi %[result], 1\n\t" + "cbi %[out], 1\n\t" + + : [result] "=r" (result) /* Outputs */ + : [out] "I" (_SFR_IO_ADDR(OWIREOUTPORT)), /* Inputs */ + [ddr] "I" (_SFR_IO_ADDR(OWIREDDR)), + [opin] "I" (OWIREOUTPIN), + [in] "I" (_SFR_IO_ADDR(OWIREINPORT)), + [ipin] "I" (OWIREINPIN) + : "r21"); /* Clobbers */ + + return(result); +} + +/*----------------------------------------------------------------------------- + * Send a 1-wire write bit. + */ +void +OWWriteBit(int bit) { + OWdelay(); + if (bit) { + asm volatile ( + /* Drive bus low */ + "cbi %[out], %[pin]\n\t" + "sbi %[ddr], %[pin]\n\t" + /* Delay A (6 usec) */ + "ldi r21, 1\n\t" + "loopA:\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopA\n\t" + /* Release bus */ + "cbi %[ddr], %[pin]\n\t" + /* Delay B (64 usec) */ + "ldi r21, 32\n\t" + "loopB:\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopB\n\t" + : /* Outputs */ + : [out] "I" (_SFR_IO_ADDR(OWIREOUTPORT)), /* Inputs */ + [ddr] "I" (_SFR_IO_ADDR(OWIREDDR)), + [pin] "I" (OWIREOUTPIN) + : "r21"); /* Clobbers */ + } else { + asm volatile ( + /* Drive bus low */ + "cbi %[out], %[pin]\n\t" + "sbi %[ddr], %[pin]\n\t" + /* Delay C (60 usec) */ + "ldi r21, 30\n\t" + "loopC:\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopC\n\t" + /* Release bus */ + "cbi %[ddr], %[pin]\n\t" + /* Delay D (10 usec) */ + "ldi r21, 9\n\t" + "loopD:\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopD\n\t" + : /* Outputs */ + : [out] "I" (_SFR_IO_ADDR(OWIREOUTPORT)), /* Inputs */ + [ddr] "I" (_SFR_IO_ADDR(OWIREDDR)), + [pin] "I" (OWIREOUTPIN) + : "r21"); /* Clobbers */ + } +} + +/*----------------------------------------------------------------------------- + * Read a bit from the 1-wire bus and return it. + */ +int +OWReadBit(void) { + uint8_t result; + + OWdelay(); + + asm volatile ( + /* Drive bus low */ + "cbi %[out], %[opin]\n\t" + "sbi %[ddr], %[opin]\n\t" + /* Delay A (6 usec) */ + "ldi r21, 1\n\t" + "loopA1:\n\t" + "dec r21\n\t" + "brne loopA1\n\t" + /* Release bus */ + "cbi %[ddr], %[opin]\n\t" + /* Delay E (9 usec) */ + "ldi r21, 8\n\t" + "loopE:\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopE\n\t" + /* Sample */ + "ldi %[res], 0\n\t" + "sbic %[in], %[ipin]\n\t" + "ldi %[res], 1\n\t" + + /* Delay F (55 usec) */ + "ldi r21, 27\n\t" + "loopF:\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "nop\n\t" + "dec r21\n\t" + "brne loopF\n\t" + + : [res] "=r" (result) /* Outputs */ + : [out] "I" (_SFR_IO_ADDR(OWIREOUTPORT)), /* Inputs */ + [ddr] "I" (_SFR_IO_ADDR(OWIREDDR)), + [opin] "I" (OWIREOUTPIN), + [in] "I" (_SFR_IO_ADDR(OWIREINPORT)), + [ipin] "I" (OWIREINPIN) + : "r21"); /* Clobbers */ + + return(result); +} + +/*----------------------------------------------------------------------------- + * Write a byte to the 1-wire bus + */ +void +OWWriteByte(uint8_t data) { + int i; + + /* Send LSB first */ + for (i = 0; i < 8; i++) { + OWWriteBit(data & 0x01); + data >>= 1; + } +} + +/*----------------------------------------------------------------------------- + * Read a byte from the 1-wire bus + */ +int +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. + */ +int +OWTouchByte(uint8_t data) { + int 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) { + int 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) + * + * Returns 1 when something is found, 0 if nothing present + */ +int +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 */ +int +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, next_result; + uint8_t rom_byte_mask; + uint8_t lastcrc8, crcaccum; + char errstr[30]; + + /* Init for search */ + bit_number = 1; + last_zero = 0; + rom_byte_number = 0; + rom_byte_mask = 1; + next_result = 0; + 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 */ +#if OW_DEBUG + uart_putsP(PSTR("Resetting\n\r")); +#endif + if (OWTouchReset()) { + /* reset the search */ + OW_LastDiscrepancy = 0; + OW_LastFamilyDiscrepancy = 0; +#if OW_DEBUG + uart_putsP(PSTR("No devices on bus\n\r")); +#endif + return 0; + } + } + + /* 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(); + OWdelay(); + OWdelay(); + + /* loop to do the search */ + do { + /* read a bit and its compliment */ + bit_test = OWReadBit() << 1; + bit_test |= OWReadBit(); + +#if OW_DEBUG + sprintf_P(errstr, PSTR("bit_test = %d\n\r"), bit_test); + uart_puts(errstr); +#endif + + /* check for no devices on 1-wire */ + if (bit_test == 3) { + sprintf_P(errstr, PSTR("bit_test = %d\n\r"), bit_test); + uart_puts(errstr); + break; + } + 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) { + sprintf_P(errstr, PSTR("Bad CRC (%d)\n\r"), lastcrc8); + uart_puts(errstr); + next_result = 0; + } else { + /* search successful so set LastDiscrepancy,LastDevice,next_result */ + OW_LastDiscrepancy = last_zero; + OW_LastDevice = (OW_LastDiscrepancy == 0); +#if OW_DEBUG + sprintf_P(errstr, PSTR("Last device = %d\n\r"), OW_LastDevice); + uart_puts(errstr); +#endif + next_result = 1; + } + } + } + + /* if no device found then reset counters so next 'next' will be + * like a first */ + if (!next_result || !ROM[0]) { + OW_LastDiscrepancy = 0; + OW_LastDevice = 0; + OW_LastFamilyDiscrepancy = 0; + next_result = 0; + } + + 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 +}; + +void +OWCRC(uint8_t x, uint8_t *crc) { + *crc = pgm_read_byte(&dscrc_table[(*crc) ^ x]); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/1wire.h Sun Jul 11 00:45:50 2004 +0930 @@ -0,0 +1,63 @@ +/* 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. + */ + +int OWTouchReset(void); +void OWWriteBit(int bit); +int OWReadBit(void); +void OWWriteByte(uint8_t data); +int OWReadByte(void); +int OWTouchByte(uint8_t data); +void OWBlock(uint8_t *data, int len); +int OWFirst(uint8_t *ROM, uint8_t do_reset, uint8_t alarm_only); +int 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); + +#define OWIREOUTPORT PORTC +#define OWIREOUTPIN 0 + +#define OWIREINPORT PINC +#define OWIREDDR DDRC +#define OWIREINPIN OWIREOUTPIN + +/* 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 + +/* Family codes */ +#define OW_FAMILY_ROM 0x09 +#define OW_FAMILY_TEMP 0x10
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Makefile Sun Jul 11 00:45:50 2004 +0930 @@ -0,0 +1,30 @@ +# Programs +PROG=avrdude +CC=avr-gcc +OBJCOPY=avr-objcopy + +# Options +PART=8515 +MCU=at90s${PART} +CFLAGS=-Os -g -mmcu=${MCU} -Wa,-adhlmsn=$(<:.c=.lst) -Wall +LDFLAGS= +LDADD= +RM=rm -f + +all: testavr.hex + +testavr.hex: testavr.out + ${OBJCOPY} -j .text -j .data -j .bss -O ihex $> $@ +# ${OBJCOPY} -j .text -O ihex $> $@ + +testavr.out: testavr.o 1wire.o + ${CC} ${LDFLAGS} -g -mmcu=${MCU} -o $@ $> + +.c.o: + ${CC} ${CFLAGS} -c $> -o $@ + +clean: + ${RM} testavr.hex testavr.out testavr.o + +prog: testavr.hex + ${PROG} -U flash:w:$> -p ${PART} -c alf -E vcc,noreset -q
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/testavr.c Sun Jul 11 00:45:50 2004 +0930 @@ -0,0 +1,274 @@ +/* + * 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. + */ + +#include <stdio.h> +#include <avr/io.h> +#include <avr/interrupt.h> +#include <avr/signal.h> +#include <avr/pgmspace.h> +#include <string.h> + +#include "1wire.h" + +#define UART_BAUD_SELECT(baudRate,xtalCpu) ((xtalCpu)/((baudRate)*16l)-1) +#define XTAL_CPU 4000000 /* 4Mhz */ +#define UART_BAUD_RATE 9600 /* 9600 baud */ + +static uint8_t dir = 0; +static volatile uint8_t leds = 0; +static uint8_t ledpos = 0; + +void uart_putsP(const char *addr); +void uart_puts(const char *addr); +int uart_putc(char c); +uint8_t uart_getc(void); + +uint8_t PROGMEM ledvals[] = {0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0xe0, 0xc0, 0x80}; + +INTERRUPT(SIG_OVERFLOW0) { + if (!leds) + return; + + /* Going up */ + if (dir == 0) { + if (ledpos == 9) { + dir = 1; + TCNT0 = 0; + goto doleds; + } + + ledpos++; + } else { + if (ledpos == 0) { + dir = 0; + TCNT0 = 0; + goto doleds; + } + + ledpos--; + } + + doleds: + TCNT0 = 0; + + PORTA = pgm_read_byte(&ledvals[ledpos]); +} + +void +usleep(uint16_t usec) { + /* 4Mhz = 250ns per clock cycle */ + usec /= 2; + if (usec < 1) + return; + + while (usec--) + asm volatile ( + "" + ::); +} + +int +main(void) { + uint8_t ROM[8], count; + char foo[40]; + int i; + + cli(); + outp(0xff, DDRA); + outp(0xfe, DDRC); + outp(0x00, PORTC); + + /* Init UART */ + outp(UART_BAUD_SELECT(UART_BAUD_RATE,XTAL_CPU), UBRR); + + /* Enable receiver and transmitter. Turn on transmit interrupts */ + outp(BV(RXEN) | BV(TXEN), UCR); + + /* Timer Clock divisor - CK/1024 */ + outp(BV(CS00) | BV(CS02), TCCR0); + + uart_putsP(PSTR("\n\r\n\r===============\n\r")); + uart_putsP(PSTR("Inited!\n\r\n\r")); + uart_putsP(PSTR("Test message 1\n\r")); + + count = 0; + while (1) { + char cmd; + + cmd = uart_getc(); + switch (cmd) { + case 'r': + uart_putsP(PSTR("Resetting... ")); + + if (OWTouchReset() == 1) + uart_putsP(PSTR("No presense\n\r")); + else + uart_putsP(PSTR("Presense\n\r")); + break; + + case 'R': + if (OWReadBit()) + uart_putsP(PSTR("Read a 1\n\r")); + else + uart_putsP(PSTR("Read a 0\n\r")); + break; + + case 'w': + OWWriteBit(0); + uart_putsP(PSTR("Wote a 0\n\r")); + break; + + case 'W': + OWWriteBit(1); + uart_putsP(PSTR("Wote a 1\n\r")); + break; + + case 'd': + bzero(ROM, 8); + if (OWTouchReset()) { + uart_putsP(PSTR("No devices on bus\n\r")); + break; + } + if (OWFirst(ROM, 1, 0) == 0) { + uart_putsP(PSTR("No module found\n\r")); + break; + } + do { + uart_putsP(PSTR("Found a module ")); + sprintf_P(foo, PSTR("%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x"), + ROM[0], + ROM[1], + ROM[2], + ROM[3], + ROM[4], + ROM[5], + ROM[6], + ROM[7]); + uart_puts(foo); + if (ROM[0] == OW_FAMILY_TEMP) { + uint8_t tempbuf[9]; + uint8_t crc; + uint16_t temp; + + uart_putsP(PSTR(" is a temp sensor\n\r")); + OWSendCmd(ROM, OW_CONVERTT_CMD); +#if OW_DEBUG + uart_putsP(PSTR("Command sent, waiting\n\r")); +#endif + i = 0; + while (OWReadBit() == 0) { + i++; + } +#if OW_DEBUG + sprintf_P(foo, PSTR("Temp comversion took %d cycles\n\r"), i); + uart_puts(foo); +#endif + OWSendCmd(ROM, OW_RD_SCR_CMD); + crc = 0; + for (i = 0; i < 9; i++) { + tempbuf[i] = OWReadByte(); + if (i < 8) + OWCRC(tempbuf[i], &crc); + } + + temp = tempbuf[0]; + temp |= (uint16_t)tempbuf[1] << 8; + temp <<= 3; + + if (crc != tempbuf[9]) { + sprintf_P(foo, PSTR("CRC mismatch got %d vs calcd %d\n\r"), tempbuf[9], crc); + uart_puts(foo); + } + + sprintf_P(foo, PSTR("temperature %d.%01d\n\r"), + temp >> 4, (temp << 12) / 6553); + uart_puts(foo); + } + + if (ROM[0] == OW_FAMILY_ROM) { + uart_putsP(PSTR(" is a ROM\n\r")); + } + } while (OWNext(ROM, 1, 0)); + break; + + case 'l': + if (leds == 0) { + leds = 1; + ledpos = 0; + outp(0, TCNT0); + sbi(TIMSK, TOIE0); + sei(); + uart_putsP(PSTR("Starting\n\r")); + } else { + leds = 0; + ledpos = 0; + PORTA = 0x00; + cbi(TIMSK, TOIE0); + cli(); + uart_putsP(PSTR("Stopping\n\r")); + } + + break; + + default: + uart_putsP(PSTR("Unknown command\n\r")); + break; + } + + } + + return(0); +} + +int +uart_putc(char c) { + loop_until_bit_is_set(USR, UDRE); + outp(c, UDR); + + return(0); +} + +void +uart_putsP(const char *addr) { + char c; + + while ((c = PRG_RDB((unsigned short)addr++))) + uart_putc(c); +} + +void +uart_puts(const char *addr) { + while (*addr) + uart_putc(*addr++); +} + +uint8_t +uart_getc(void) { + while (!(inp(USR) & 0x80)) + ; + + return (inp(UDR)); +}