Revision 168:bfc84ee2839b

b/.hgignore
24 24
*.egg
25 25
*.map
26 26
*.img
27
.swp
b/analog_exp/Makefile
1
# Generic AVR Makefile
2
# Brian Mayton <bmayton@media.mit.edu>
3
#
4
# This is a basic Makefile for building programs for the AVR.  I usually start
5
# with this for any new project; it's pretty versatile.
6
#
7
# 'make' builds the .hex file.
8
# 'make install' uses the programmer to load it onto the target chip.
9
# 'make fuses' programs the fuse bits on the target chip.
10
# 'make clean' removes all autogenerated files.
11

  
12
# OBJECTS should list all of the object files for the program (e.g. for each
13
# .c file, list a corresponding .o file here.)  APPLICATION just specifies the
14
# name of the hex/elf files, and can be whatever you want. 
15
OBJECTS = \
16
	analog_exp.o \
17
	uart.o \
18
	debug.o \
19
	onewire.o \
20
	onewire_hal_bitbang.o \
21
	excitation.o \
22

  
23
APPLICATION = analog_exp
24

  
25
# Set up which MCU you're using, and what programmer, and the clock speed
26
# here.
27
MCU = atmega168p
28
PROGRAMMER = jtag2isp
29
F_CPU = 8000000UL
30

  
31
# Make sure you check these fuse settings before actually using them, using
32
# fuse settings for the wrong clock setup or chip can make it hard to
33
# reprogram.  http://www.engbedded.com/fusecalc/ is very useful!
34
EFUSE=0x01
35
HFUSE=0xD7
36
LFUSE=0xE2
37

  
38
# Edit these if you want to use different compilers
39
CC = avr-gcc
40
OBJCOPY = avr-objcopy
41
SIZE = avr-size
42
AVRDUDE = avrdude
43

  
44
# Compiler and linker flags
45
CFLAGS=-mmcu=$(MCU) -Wall -DF_CPU=$(F_CPU) -I. -funsigned-char \
46
	-funsigned-bitfields -fpack-struct -fshort-enums -Os -DDEBUG --std=gnu99
47
LDFLAGS=-mmcu=$(MCU)
48

  
49
all: $(APPLICATION).hex
50

  
51
clean:
52
	rm -f *.hex *.elf *.o 
53

  
54
%.hex: %.elf
55
	$(OBJCOPY) -j .text -j .data -O ihex $< $@
56

  
57
$(APPLICATION).elf: $(OBJECTS)
58
	$(CC) $(LDFLAGS) -o $@ $^
59
	$(SIZE) -C --mcu=$(MCU) $@
60

  
61
%.o: %.c
62
	$(CC) $(CFLAGS) -c $< -o $@
63

  
64
install: all
65
	$(AVRDUDE) -p $(MCU) -c $(PROGRAMMER) -P usb -e \
66
		-U flash:w:$(APPLICATION).hex
67

  
68
fuses:
69
	$(AVRDUDE) -p $(MCU) -c $(PROGRAMMER) -P usb -e \
70
		-U lfuse:w:$(LFUSE):m -U hfuse:w:$(HFUSE):m \
71
		-U efuse:w:$(EFUSE):m
72

  
73
.PHONY: all clean install fuses
74

  
b/analog_exp/analog_exp.c
1 1
#include <avr/io.h>
2 2
#include <avr/interrupt.h>
3
#include <util/delay.h>
3 4

  
4 5
#include "board.h"
6
#include "debug.h"
7
#include "onewire.h"
8
#include "excitation.h"
5 9
#include "analog_exp.h"
6 10

  
11
onewire_id onewire_devices[4];
12

  
7 13
static inline void setup(void) {
14
    debug_setup();
15
    exc_setup();
8 16

  
17
    exc_enable(0, 0xFF);
9 18
}
10 19

  
11 20
static inline void loop(void) {
21
    ds18b20_scratchpad_t scratchpad;
12 22

  
23
    _delay_ms(1000);
24
    uint8_t n_devices = 4;
25
    onewire_searchrom(onewire_devices, &n_devices);
26

  
27
    onewire_skiprom();
28
    onewire_convert_t();
29
    _delay_ms(750);
30

  
31
    debugf("%d devices\n", n_devices);
32
    for(uint8_t i=0; i<n_devices; i++) {
33
        debugf("  0x");
34
        for(uint8_t j=0; j<sizeof(onewire_id); j++) {
35
            debugf("%02X", onewire_devices[i][j]);
36
        }
37
        uint8_t crc = onewire_crc_rom(onewire_devices[i]);
38
        debugf(" crc: %d\n", crc);
39

  
40
        onewire_matchrom(onewire_devices[i]);
41
        crc = onewire_read_scratchpad(&scratchpad);
42
        debugf("    scratchpad crc: %d\n", crc);
43
        debugf("    temperature: %d.%04d\n", scratchpad.temperature >> 4, 
44
            (scratchpad.temperature & 0xF) * 625 );
45
    }
13 46
}
14 47

  
15 48
int main(void) {
b/analog_exp/board.h
8 8
#define ADC_INT         PB0
9 9

  
10 10
/* 1-wire bus */
11
#define 1W_PORT         PORTB
12
#define 1W_PIN          PINB
13
#define 1W_DDR          DDRB
14
#define 1W              PB1
11
#define ONEWIRE_PORT         PORTB
12
#define ONEWIRE_PIN          PINB
13
#define ONEWIRE_DDR          DDRB
14
#define ONEWIRE              PB1
15 15

  
16 16
/* SPI control of digital potentiometers for excitation voltage */
17 17
#define EXC_SPI_PORT    PORTB
b/analog_exp/debug.c
1
#include <stdio.h>
2

  
3
#include "uart.h"
4
#include "debug.h"
5

  
6
#ifdef DEBUG
7
static FILE uart_stream = FDEV_SETUP_STREAM(
8
    uart_putchar_f,
9
    uart_getchar_f,
10
    _FDEV_SETUP_RW
11
);
12
#endif
13

  
14
void debug_setup(void) {
15
#ifdef DEBUG
16
    stdout = &uart_stream;
17
    stderr = &uart_stream;
18
    uart_setup();
19
#endif
20
}
21

  
22
#ifdef DEBUG
23
void debug_printf(const char *fmt, ...) {
24
    va_list args;
25
    va_start(args, fmt);
26
    vfprintf_P(&uart_stream, fmt, args);
27
    va_end(args);
28
}
29
#endif
30

  
b/analog_exp/debug.h
1
#ifndef __debug_h_
2
#define __debug_h_
3

  
4
#include <avr/pgmspace.h>
5

  
6
void debug_setup(void);
7

  
8
#ifdef DEBUG
9
    void debug_printf(const char *fmt, ...);
10
#   define debugf(format, ...) { \
11
        debug_printf(PSTR(format), ## __VA_ARGS__); \
12
    }
13
#else
14
#   define debugf(format, ...)
15
#endif
16

  
17
#endif // __debug_h_
18

  
b/analog_exp/excitation.c
1
#include <avr/io.h>
2

  
3
#include "board.h"
4
#include "excitation.h"
5

  
6
#define SPI_CS_HIGH() EXC_SPI_PORT |=  (1<<EXC_SPI_SS)
7
#define SPI_CS_LOW()  EXC_SPI_PORT &= ~(1<<EXC_SPI_SS)
8

  
9
void exc_setup(void) {
10
    SPI_CS_HIGH();
11
    EXC_SPI_DDR |= (1<<EXC_SPI_MOSI) | (1<<EXC_SPI_SCK) | (1<<EXC_SPI_SS);
12
    SPCR = (1<<SPE) | (1<<MSTR);
13

  
14
    EXC_EN_DDR |= (1<<EXC_VEN0) | (1<<EXC_VEN1);
15
}
16

  
17
static uint8_t spi_transfer(uint8_t data) {
18
    SPDR = data;
19
    while(! (SPSR & (1<<SPIF)));
20
    return SPDR;
21
}
22

  
23
void exc_power_on(bool on) {
24
    SPI_CS_LOW();
25
    spi_transfer(EXC_CMD_ACR_WRITE);
26
    spi_transfer(on? EXC_SHDN_bm : 0);
27
    SPI_CS_HIGH();
28
}
29

  
30
void exc_enable(uint8_t ch, uint8_t value) {
31
    exc_power_on(true);
32
    SPI_CS_LOW();
33
    spi_transfer(EXC_CMD_WRITE | ch);
34
    spi_transfer(value);
35
    SPI_CS_HIGH();
36

  
37
    EXC_EN_PORT |= (ch? (1<<EXC_VEN1) : (1<<EXC_VEN0));
38
}
39

  
40
void exc_disable(uint8_t ch) {
41
    EXC_EN_PORT &= ~(ch? (1<<EXC_VEN1) : (1<<EXC_VEN0));
42
    if((EXC_EN_PORT & ((1<<EXC_VEN1) | (1<<EXC_VEN0))) == 0) {
43
        exc_power_on(false);
44
    }
45
}
46

  
b/analog_exp/excitation.h
1
#ifndef __excitation_h_
2
#define __excitation_h_
3

  
4
#include <stdint.h>
5
#include <stdbool.h>
6

  
7
void exc_setup(void);
8
void exc_power_on(bool on);
9
void exc_enable(uint8_t ch, uint8_t value);
10
void exc_disable(uint8_t ch);
11

  
12
#define EXC_CMD_ACR_READ 0x20
13
#define EXC_CMD_ACR_WRITE 0x60
14
#define EXC_CMD_READ 0x80
15
#define EXC_CMD_WRITE 0xC0
16

  
17
#define EXC_REG_ACR 0x10
18
#define EXC_REG_WR1 0x1
19
#define EXC_REG_WR0 0x0
20

  
21
#define EXC_SHDN_bm (1<<6)
22
#define EXC_SDO_bm = (1<<1)
23

  
24
#endif // __excitation_h_
25

  
b/analog_exp/onewire.c
1
#include <string.h>
2

  
3
#include "debug.h"
1 4
#include "onewire_hal.h"
2 5
#include "onewire.h"
3 6

  
......
12 15
    }
13 16
}
14 17

  
15
uint8_t onewire_rx_byte(uint8_t data) {
18
uint8_t onewire_rx_byte(void) {
16 19
    uint8_t data = 0;
17 20
    for(uint8_t i=0; i<8; i++) {
18 21
        data >>= 1;
......
22 25
}
23 26

  
24 27
void onewire_readrom(onewire_id id) {
28
    onewire_reset();
25 29
    onewire_tx_byte(ONEWIRE_CMD_READROM);
26 30
    for(uint8_t i=0; i<8; i++) {
27 31
        id[i] = onewire_rx_byte();
......
29 33
}
30 34

  
31 35
void onewire_matchrom(onewire_id id) {
36
    onewire_reset();
32 37
    onewire_tx_byte(ONEWIRE_CMD_MATCHROM);
33 38
    for(uint8_t i=0; i<8; i++) {
34 39
        onewire_tx_byte(id[i]);
35 40
    }
36 41
}
37 42

  
43
void onewire_skiprom(void) {
44
    onewire_reset();
45
    onewire_tx_byte(ONEWIRE_CMD_SKIPROM);
46
}
47

  
38 48
typedef struct {
39 49
    bool done;
40 50
    uint8_t next_id;
......
66 76
                state->bit_pattern[bit_index / 8] |=  (1<<(bit_index % 8));
67 77
            } else if(bit_index > state->prev_deviation) {
68 78
                state->bit_pattern[bit_index / 8] &= ~(1<<(bit_index % 8));
69
            } else if(bit_pattern[bit_index / 8] & (1<<(bit_index % 8)) == 0) {
79
                deviation = bit_index;
80
            } else if((state->bit_pattern[bit_index / 8] & (1<<(bit_index % 8))) == 0) {
70 81
                deviation = bit_index;
71 82
            }
72 83
        }
73
        if(bit_pattern[bit_index / 8] & (1<<(bit_index % 8))) {
84
        if(state->bit_pattern[bit_index / 8] & (1<<(bit_index % 8))) {
74 85
            onewire_tx1();
75 86
        } else {
76 87
            onewire_tx0();
77 88
        }
78 89
    }
79
    if(deviation = -1) state->done = true;
90
    if(deviation == -1) state->done = true;
80 91
    state->prev_deviation = deviation;
81 92
    return true;
82 93
}
......
85 96
    onewire_search_state_t state;
86 97
    state.done = false;
87 98
    state.next_id = 0;
88
    state.deviation = -1;
89
    memset(bit_pattern, 0, sizeof(onewire_id));
99
    state.prev_deviation = -1;
100
    memset(state.bit_pattern, 0, sizeof(onewire_id));
90 101
    
91 102
    while(*n > 0 && onewire_search_iter(&state)) {
92 103
        memcpy(id_list[state.next_id++], state.bit_pattern, sizeof(onewire_id));
93
        *n--;
104
        *n = *n - 1;
94 105
    }
95 106

  
96 107
    *n = state.next_id;
97 108
}
98 109

  
110
static uint8_t onewire_crc8_byte(uint8_t seed, uint8_t data) {
111
    const uint8_t poly = 0x18;
112
    for(uint8_t i=0; i<8; i++) {
113
        if((data ^ seed) & 1) {
114
            seed = ((seed ^ poly) >> 1) | 0x80;
115
        } else {
116
            seed >>= 1;
117
        }
118
        data >>= 1;
119
    }
120
    return seed;
121
}
122

  
123
uint8_t onewire_crc8(uint8_t *data, uint8_t length) {
124
    uint8_t crc = 0;
125
    for(; length > 0; length--) {
126
        crc = onewire_crc8_byte(crc, *data++);
127
    }
128
    return crc;
129
}
130

  
131
bool onewire_crc_rom(onewire_id id) {
132
    return onewire_crc8(id, 8) == 0;
133
}
134

  
135
void onewire_convert_t(void) {
136
    onewire_tx_byte(ONEWIRE_CMD_CONVERT_T);
137
}
138

  
139
void onewire_write_scratchpad(uint8_t th, uint8_t tl, uint8_t config) {
140
    onewire_tx_byte(ONEWIRE_CMD_WRITE_SCRATCHPAD);
141
    onewire_tx_byte(th);
142
    onewire_tx_byte(tl);
143
    onewire_tx_byte(config);
144
}
145

  
146
bool onewire_read_scratchpad(ds18b20_scratchpad_t *scratchpad) {
147
    onewire_tx_byte(ONEWIRE_CMD_READ_SCRATCHPAD);
148
    uint8_t *buf = (uint8_t*)scratchpad;
149
    for(uint8_t i=0; i<sizeof(ds18b20_scratchpad_t); i++) {
150
        *buf++ = onewire_rx_byte();
151
    }
152

  
153
    return onewire_crc8((uint8_t*)scratchpad, sizeof(ds18b20_scratchpad_t)) == 0;
154
}
155

  
b/analog_exp/onewire.h
2 2
#define __onewire_h_
3 3

  
4 4
#include <stdint.h>
5
#include <stdbool.h>
5 6

  
6
typedef char[8] onewire_id;
7
typedef uint8_t onewire_id[8];
8

  
9
typedef struct {
10
    int16_t temperature;
11
    uint8_t threshold_h;
12
    uint8_t threshold_l;
13
    uint8_t config;
14
    uint8_t resv0;
15
    uint8_t resv1;
16
    uint8_t resv2;
17
    uint8_t crc;
18
} ds18b20_scratchpad_t;
7 19

  
8 20
void onewire_tx_byte(uint8_t data);
9 21
uint8_t onewire_rx_byte(void);
10 22
void onewire_readrom(onewire_id id);
11 23
void onewire_matchrom(onewire_id id);
24
void onewire_skiprom(void);
12 25
void onewire_searchrom(onewire_id *id_list, uint8_t *n);
26
uint8_t onewire_crc8(uint8_t *data, uint8_t length);
27
bool onewire_crc_rom(onewire_id id);
28

  
29
void onewire_convert_t(void);
30
void onewire_write_scratchpad(uint8_t th, uint8_t tl, uint8_t config);
31
bool onewire_read_scratchpad(ds18b20_scratchpad_t *scratchpad);
13 32

  
14 33
#define ONEWIRE_CMD_READROM 0x33
15 34
#define ONEWIRE_CMD_SKIPROM 0xCC
16 35
#define ONEWIRE_CMD_MATCHROM 0x55
17 36
#define ONEWIRE_CMD_SEARCHROM 0xF0
18 37

  
38
#define ONEWIRE_CMD_CONVERT_T 0x44
39
#define ONEWIRE_CMD_WRITE_SCRATCHPAD 0x4E
40
#define ONEWIRE_CMD_READ_SCRATCHPAD 0xBE
41
#define ONEWIRE_CMD_COPY_SCRATCHPAD 0x48
42
#define ONEWIRE_CMD_RECALL_EE 0xB8
43
#define ONEWIRE_CMD_READ_POWER 0xB4
44

  
19 45
#endif // __onewire_h_
20 46

  
b/analog_exp/onewire_hal_bitbang.c
5 5
#include "board.h"
6 6
#include "onewire_hal.h"
7 7

  
8
#define 1W_LOW()  1W_DDR |=  (1<<1W)
9
#define 1W_HIGH() 1W_DDR &= ~(1<<1W)
10
#define 1W_IN     ((1W_PIN & (1<<1W)) >> 1W)
8
#define ONEWIRE_LOW()  ONEWIRE_DDR |=  (1<<ONEWIRE)
9
#define ONEWIRE_HIGH() ONEWIRE_DDR &= ~(1<<ONEWIRE)
10
#define ONEWIRE_IN     ((ONEWIRE_PIN & (1<<ONEWIRE)) >> ONEWIRE)
11 11

  
12 12
bool onewire_reset(void) {
13 13
    bool presence;
14 14
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
15
        1W_PORT &= ~(1<<1W);
16
        1W_LOW();
15
        ONEWIRE_PORT &= ~(1<<ONEWIRE);
16
        ONEWIRE_LOW();
17 17
        _delay_us(480);
18
        1W_HIGH();
18
        ONEWIRE_HIGH();
19 19
        _delay_us(70);
20
        presence = (1W_IN == 0);
21
        __delay_us(410);
20
        presence = (ONEWIRE_IN == 0);
21
        _delay_us(410);
22 22
    }
23 23
    return presence;
24 24
}
25 25

  
26 26
inline void onewire_tx1(void) {
27 27
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
28
        1W_LOW();
28
        ONEWIRE_LOW();
29 29
        _delay_us(6);
30
        1W_HIGH();
30
        ONEWIRE_HIGH();
31 31
        _delay_us(64);
32 32
    }
33 33
}
34 34

  
35 35
inline void onewire_tx0(void) {
36 36
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
37
        1W_LOW();
37
        ONEWIRE_LOW();
38 38
        _delay_us(60);
39
        1W_HIGH();
39
        ONEWIRE_HIGH();
40 40
        _delay_us(10);
41 41
    }
42 42
}
......
44 44
inline uint8_t onewire_rx(void) {
45 45
    uint8_t bit;
46 46
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
47
        1W_LOW();
47
        ONEWIRE_LOW();
48 48
        _delay_us(6);
49
        1W_HIGH();
49
        ONEWIRE_HIGH();
50 50
        _delay_us(9);
51
        bit = 1W_IN;
51
        bit = ONEWIRE_IN;
52 52
        _delay_us(55);
53 53
    }
54 54
    return bit;
b/analog_exp/uart.c
1
#include <avr/io.h>
2
#include <avr/interrupt.h>
3
#include "uart.h"
4

  
5
// UART buffers
6
volatile char rxbuf[64];
7
volatile uint8_t rdptr = 0;
8
volatile uint8_t wrptr = 0;
9

  
10
/**
11
 * Set up the UART
12
 */
13
void uart_setup(void) {
14
    DDRD |= (1<<TXD_PIN);
15
	UBRR0H = 0;
16
	UBRR0L = 25;
17
	UCSR0A |= (0<<U2X0);
18
	UCSR0B |= (1<<RXEN0) | (1<<TXEN0) | (1<<RXCIE0);
19
}
20

  
21
void uart_putchar(uint8_t c) {
22
	while( ! (UCSR0A & (1<<UDRE0)) );
23
	UDR0 = c;
24
}
25

  
26
int uart_putchar_f(char c, FILE *stream) {
27
    if(c == '\n') uart_putchar_f('\r', stream);
28
	while( ! (UCSR0A & (1<<UDRE0)) );
29
	UDR0 = c;
30
    return 0;
31
}
32

  
33
void uart_putdata(uint8_t *data, uint8_t count) {
34
	int i;
35
	for(i=0; i<count; i++) uart_putchar(data[i]);
36
}
37

  
38
uint8_t uart_data_available() {
39
    return !(rdptr == wrptr);
40
}
41

  
42
int16_t uart_getchar(uint8_t blocking) {
43
	char c;
44
    if(blocking)
45
        while(rdptr == wrptr);
46
    else
47
        if(rdptr == wrptr) return -1;
48
	c = rxbuf[rdptr];
49
	rdptr = (rdptr + 1) & 63;
50
	return c;
51
}
52

  
53
int uart_getchar_f(FILE *stream) {
54
    char c;
55
    while(rdptr == wrptr);
56
    c = rxbuf[rdptr];
57
    rdptr = (rdptr + 1) & 63;
58
    return c;
59
}
60

  
61
/**
62
 * UART Receive ISR
63
 */
64
ISR(USART_RX_vect) {
65
	rxbuf[wrptr] = UDR0;
66
    //uart_putchar(rxbuf[wrptr]);
67
	wrptr = (wrptr + 1) & 63;
68
	if(wrptr == rdptr) rdptr = (rdptr + 1) & 63;
69
}
70

  
b/analog_exp/uart.h
1
#ifndef __uart_h_
2
#define __uart_h_
3

  
4
#include <stdio.h>
5

  
6
#define RXD_PIN 0
7
#define TXD_PIN 1
8

  
9
void uart_setup(void);
10
int16_t uart_getchar(uint8_t blocking);
11
void uart_putchar(uint8_t c);
12
void uart_putdata(uint8_t *data, uint8_t count);
13
uint8_t uart_data_available();
14

  
15
int uart_getchar_f(FILE *stream);
16
int uart_putchar_f(char c, FILE *stream);
17

  
18
#endif // __uart_h_
19

  

Also available in: Unified diff