summaryrefslogtreecommitdiffstats
path: root/pressure_control/firmware
diff options
context:
space:
mode:
authorMichael Buesch <mb@bu3sch.de>2008-10-18 23:47:05 +0200
committerMichael Buesch <mb@bu3sch.de>2008-10-18 23:47:05 +0200
commit4b0babc1b1daaece0d8de672f98adaf6cff5cdac (patch)
tree58c4bbac00ca8a76af06b006a392279ae6729907 /pressure_control/firmware
parent4a914e8c559cd48173bed088e2122d1d35c8de9b (diff)
downloadcnc-4b0babc1b1daaece0d8de672f98adaf6cff5cdac.tar.xz
cnc-4b0babc1b1daaece0d8de672f98adaf6cff5cdac.zip
Add a loooot of stuff to pressure_control
Signed-off-by: Michael Buesch <mb@bu3sch.de>
Diffstat (limited to 'pressure_control/firmware')
-rw-r--r--pressure_control/firmware/Makefile16
-rw-r--r--pressure_control/firmware/main.c195
-rw-r--r--pressure_control/firmware/main.h36
-rw-r--r--pressure_control/firmware/remote.c243
-rw-r--r--pressure_control/firmware/remote.h68
-rw-r--r--pressure_control/firmware/sensor.c55
-rw-r--r--pressure_control/firmware/sensor.h4
-rw-r--r--pressure_control/firmware/util.c37
-rw-r--r--pressure_control/firmware/util.h3
9 files changed, 589 insertions, 68 deletions
diff --git a/pressure_control/firmware/Makefile b/pressure_control/firmware/Makefile
index 4024f02..a725d24 100644
--- a/pressure_control/firmware/Makefile
+++ b/pressure_control/firmware/Makefile
@@ -17,7 +17,7 @@ CFLAGS += "-Dinline=inline __attribute__((__always_inline__))"
LFUSE = 0xE0
HFUSE = 0xD9
-OBJECTS = main.o util.o valves.o sensor.o
+OBJECTS = main.o util.o valves.o sensor.o remote.o
NAME = pressure_control
BIN = $(NAME).bin
@@ -26,13 +26,15 @@ EEP = $(NAME).eep.hex
all: $(HEX)
-main.o: util.h calibration.h valves.h sensor.h
+main.o: util.h calibration.h valves.h sensor.h remote.h main.h
util.o: util.h calibration.h
-valves.o: valves.h
+valves.o: util.h valves.h
-sensor.o: sensor.h
+sensor.o: util.h sensor.h
+
+remote.o: util.h remote.h calibration.h main.h
%.s: %.c
$(CC) $(CFLAGS) -S $*.c
@@ -42,8 +44,8 @@ $(BIN): $(OBJECTS)
$(HEX): $(BIN)
$(OBJCOPY) -R.eeprom -O ihex $(BIN) $(HEX)
-# $(OBJCOPY) -j.eeprom --set-section-flags=.eeprom="alloc,load" \
-# --change-section-lma .eeprom=0 -O ihex $(BIN) $(EEP)
+ $(OBJCOPY) -j.eeprom --set-section-flags=.eeprom="alloc,load" \
+ --change-section-lma .eeprom=0 -O ihex $(BIN) $(EEP)
$(SIZE) $(BIN)
avrdude:
@@ -58,7 +60,7 @@ install_eeprom:
$(AVRDUDE) -B $(AVRDUDE_SPEED) -p $(AVRDUDE_ARCH) \
-c $(PROGRAMMER) -P $(PROGPORT) -U eeprom:w:$(EEP)
-install: all install_flash
+install: all install_flash install_eeprom
# Reset the microcontroller through avrdude
reset:
diff --git a/pressure_control/firmware/main.c b/pressure_control/firmware/main.c
index 02272ef..3dab38e 100644
--- a/pressure_control/firmware/main.c
+++ b/pressure_control/firmware/main.c
@@ -17,87 +17,180 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include "main.h"
#include "util.h"
#include "calibration.h"
#include "sensor.h"
#include "valves.h"
+#include "remote.h"
+#include <stdint.h>
+#include <string.h>
-static inline void usart_tx(uint8_t data)
+#include <avr/eeprom.h>
+
+
+struct eeprom_data {
+ struct pressure_config cfg;
+};
+
+/* The pressure configuration data. */
+struct pressure_config cfg;
+/* The pressure state data. */
+struct pressure_state state;
+
+/* EEPROM contents */
+static struct eeprom_data EEMEM eeprom = {
+ .cfg = {
+ .desired = 4000, /* 4 Bar */
+ .hysteresis = 300, /* 0.3 Bar */
+ .autoadjust_enable = 1,
+ },
+};
+
+
+void get_pressure_config(struct pressure_config *ret)
{
- while (!(UCSRA & (1 << UDRE)))
- ;
- UDR = data;
+ uint8_t sreg;
+
+ sreg = irq_disable_save();
+ memcpy(ret, &cfg, sizeof(*ret));
+ irq_restore(sreg);
}
-static void __print(const prog_char *msg)
+void get_pressure_state(struct pressure_state *ret)
{
- uint8_t c;
+ uint8_t sreg;
- for ( ; ; msg++) {
- c = pgm_read_byte(msg);
- if (c == '\0')
- break;
- usart_tx(c);
- }
+ sreg = irq_disable_save();
+ memcpy(ret, &state, sizeof(*ret));
+ irq_restore(sreg);
}
-#define print(msg) __print(PSTR(msg))
-#define ERXFE 1 /* USART RX frame error */
-#define ERXPE 2 /* USART RX parity error */
-#define ERXOV 3 /* USART RX hardware buffer overflow */
-#define ENODATA 4 /* No data available */
+/* Load the configuration from the EEPROM. */
+static void eeprom_load_config(void)
+{
+ eeprom_busy_wait();
+ eeprom_read_block(&cfg, &eeprom.cfg, sizeof(cfg));
+ eeprom_busy_wait();
+}
-static inline int8_t usart_rx(uint8_t *data)
+/* Store the configuration to the EEPROM. */
+static void eeprom_store_config(void)
{
- uint8_t status;
-
- status = UCSRA;
- if (!(status & (1 << RXC)))
- return -ENODATA;
- if (unlikely(status & ((1 << FE) | (1 << PE) | (1 << DOR)))) {
- if (status & (1 << FE))
- return -ERXFE;
- if (status & (1 << PE))
- return -ERXPE;
- if (status & (1 << DOR))
- return -ERXOV;
- }
- *data = UDR;
+ eeprom_busy_wait();
+ eeprom_write_block(&cfg, &eeprom.cfg, sizeof(cfg));
+ eeprom_busy_wait();
+}
- return 0;
+/* Sensor measurement completed.
+ * Called in IRQ context. */
+void sensor_result(uint16_t mbar)
+{
+ /* Defer processing of the value to the mainloop, so we can do it with
+ * interrupts enabled. */
+ state.mbar = mbar;
+ mb();
+ state.needs_checking = 1;
}
-#define BAUDRATE 9600
+/* 1kHz system timer. */
+ISR(TIMER1_COMPA_vect)
+{
+ if (state.sensor_trigger_cnt > 0)
+ state.sensor_trigger_cnt--;
+}
-static void usart_init(void)
+void system_timer_init(void)
{
- uint8_t dummy;
-
- /* Set baud rate */
- UBRRL = lo8((CPU_HZ / 16 / BAUDRATE) * 2);
- UBRRH = hi8((CPU_HZ / 16 / BAUDRATE) * 2) & ~(1 << URSEL);
- UCSRA = (1 << U2X);
- /* 8 Data bits, 2 Stop bits, Even parity */
- UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1) | (1 << UPM1) | (1 << USBS);
- /* Enable transceiver and RX IRQs */
- UCSRB = (1 << RXEN) | (1 << TXEN);// | (1 << RXCIE);
- /* Drain the RX buffer */
- while (usart_rx(&dummy) != -ENODATA)
- mb();
+ TCCR1B = (1 << WGM12) | (1 << CS10) | (1 << CS11); /* prescaler 64 */
+ OCR1A = 250; /* 1kHz timer at 16MHz crystal */
+ TIMSK |= (1 << OCIE1A);
+}
+
+static void valves_force_state(uint8_t new_state)
+{
+ if (state.valves == new_state)
+ return;
+ valves_global_switch(new_state);
+ state.valves = new_state;
+}
+
+static void adjust_pressure(uint16_t abs_offset, bool raise_pressure)
+{
+ if (0) {
+ //TODO if offset<value do only a short valve-open time.
+ valves_force_state(VALVES_IDLE);
+
+ } else {
+ /* Open the valve. It's closed again next time we check
+ * the pressure and it's OK. */
+ if (raise_pressure)
+ valves_force_state(VALVES_FLOW_IN);
+ else
+ valves_force_state(VALVES_FLOW_OUT);
+ }
+}
+
+/* Check the current pressure value against the desired value and
+ * adjust the pressure if needed. */
+static void check_pressure(void)
+{
+ int32_t offset;
+ uint16_t abs_offset;
+ bool is_too_big;
+
+ if (!cfg.autoadjust_enable)
+ return;
+
+ offset = (int32_t)state.mbar - (int32_t)cfg.desired;
+ abs_offset = abs(offset);
+ is_too_big = (offset >= 0);
+
+ if (abs_offset > cfg.hysteresis) {
+ /* Adjust the pressure */
+ adjust_pressure(abs_offset, !is_too_big);
+ } else {
+ /* The pressure is OK. Make sure the valves are
+ * all idle. */
+ valves_force_state(VALVES_IDLE);
+ }
}
int main(void)
{
cli();
+ /* It's OK to init the remote interface that early, as we
+ * have IRQs disabled throughout the init process. So we can't
+ * receive any remote commands, yet. But early init allows us
+ * to send error messages early. */
+ remote_init();
+ print("Pressure control initializing...\n");
+
valves_init();
- usart_init();
+ state.valves = VALVES_IDLE;
+ sensor_init();
+ eeprom_load_config();
+ system_timer_init();
sei();
+ print("Monitoring...\n");
while (1) {
- print("Hallo!\n");
- //TODO
+ mb();
+ if (state.sensor_trigger_cnt == 0) {
+ /* It's time for triggering another sensor measurement. */
+ state.sensor_trigger_cnt = -1;
+ mb();
+ sensor_trigger_read();
+ }
+ if (state.needs_checking) {
+ check_pressure();
+ /* Trigger another measurement in 50 milliseconds. */
+ state.sensor_trigger_cnt = 50;
+ mb();
+ }
+ remote_work();
}
}
diff --git a/pressure_control/firmware/main.h b/pressure_control/firmware/main.h
new file mode 100644
index 0000000..abdfa8f
--- /dev/null
+++ b/pressure_control/firmware/main.h
@@ -0,0 +1,36 @@
+#ifndef MAIN_H_
+#define MAIN_H_
+
+#include "util.h"
+
+#include <stdint.h>
+
+
+struct pressure_config {
+ /* Desired pressure in mBar */
+ uint16_t desired;
+ /* Pressure hysteresis in mBar */
+ uint16_t hysteresis;
+ /* Auto-adjustment is enabled. */
+ bool autoadjust_enable;
+};
+
+struct pressure_state {
+ /* Current pressure in the tank (in mBar) */
+ uint16_t mbar;
+ /* True, if the current pressure value needs checking against
+ * the desired pressure config. */
+ bool needs_checking;
+ /* Trigger count:
+ * >0 = waiting
+ * 0 = trigger now
+ * -1 = triggered and running. */
+ int8_t sensor_trigger_cnt;
+ /* Current valves state (enum valves_global_state) */
+ uint8_t valves;
+};
+
+void get_pressure_config(struct pressure_config *cfg);
+void get_pressure_state(struct pressure_state *state);
+
+#endif /* MAIN_H_ */
diff --git a/pressure_control/firmware/remote.c b/pressure_control/firmware/remote.c
new file mode 100644
index 0000000..d759e7a
--- /dev/null
+++ b/pressure_control/firmware/remote.c
@@ -0,0 +1,243 @@
+/*
+ * Pneumatic pressure controller.
+ * Remote control.
+ *
+ * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "remote.h"
+#include "util.h"
+#include "calibration.h"
+#include "main.h"
+
+#include <string.h>
+
+#include <avr/io.h>
+
+
+#define BAUDRATE 9600
+
+
+static struct remote_message rx_msg;
+static uint8_t rx_msg_count;
+static bool rx_msg_valid;
+
+
+static inline void usart_tx(uint8_t data)
+{
+ while (!(UCSRA & (1 << UDRE)))
+ ;
+ UDR = data;
+}
+
+static void usart_tx_buf(const void *_buf, uint8_t size)
+{
+ const uint8_t *buf = _buf;
+
+ while (size) {
+ usart_tx(*buf);
+ buf++;
+ size--;
+ }
+}
+
+#define ERXFE 1 /* USART RX frame error */
+#define ERXPE 2 /* USART RX parity error */
+#define ERXOV 3 /* USART RX hardware buffer overflow */
+#define ENODATA 4 /* No data available */
+
+static inline int8_t usart_rx(uint8_t *data)
+{
+ uint8_t status;
+
+ status = UCSRA;
+ if (!(status & (1 << RXC)))
+ return -ENODATA;
+ if (unlikely(status & ((1 << FE) | (1 << PE) | (1 << DOR)))) {
+ if (status & (1 << FE))
+ return -ERXFE;
+ if (status & (1 << PE))
+ return -ERXPE;
+ if (status & (1 << DOR))
+ return -ERXOV;
+ }
+ *data = UDR;
+
+ return 0;
+}
+
+static void send_message(struct remote_message *msg)
+{
+ /* Calculate the CRC. */
+ msg->crc = crc16_block_update(0xFFFF, msg,
+ sizeof(*msg) - sizeof(msg->crc));
+ msg->crc ^= 0xFFFF;
+ /* And transmit the bits. */
+ usart_tx_buf(msg, sizeof(*msg));
+}
+
+static void send_message_error(uint8_t error_code)
+{
+ struct remote_message msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.id = MSG_ERROR;
+ msg.error.code = error_code;
+
+ send_message(&msg);
+}
+
+static void handle_received_message(void)
+{
+ struct remote_message reply;
+ uint16_t calc_crc;
+
+ calc_crc = crc16_block_update(0xFFFF, &rx_msg,
+ sizeof(rx_msg) - sizeof(rx_msg.crc));
+ calc_crc ^= 0xFFFF;
+ if (calc_crc != rx_msg.crc) {
+ /* CRC mismatch. */
+ send_message_error(MSG_ERR_CHKSUM);
+ return;
+ }
+ memset(&reply, 0, sizeof(reply));
+
+ switch (rx_msg.id) {
+ case MSG_PING:
+ reply.id = MSG_PONG;
+ send_message(&reply);
+ break;
+ case MSG_GET_CURRENT_PRESSURE: {
+ struct pressure_state state;
+
+ get_pressure_state(&state);
+ reply.id = MSG_CURRENT_PRESSURE;
+ reply.pressure.mbar = state.mbar;
+ send_message(&reply);
+ break;
+ }
+ case MSG_GET_DESIRED_PRESSURE: {
+ struct pressure_config conf;
+
+ get_pressure_config(&conf);
+ reply.id = MSG_DESIRED_PRESSURE;
+ reply.pressure.mbar = conf.desired;
+ send_message(&reply);
+ break;
+ }
+ case MSG_GET_HYSTERESIS: {
+ struct pressure_config conf;
+
+ get_pressure_config(&conf);
+ reply.id = MSG_HYSTERESIS;
+ reply.pressure.mbar = conf.hysteresis;
+ send_message(&reply);
+ break;
+ }
+ case MSG_GET_CONFIG_FLAGS: {
+ struct pressure_config conf;
+
+ get_pressure_config(&conf);
+ reply.id = MSG_CONFIG_FLAGS;
+ if (conf.autoadjust_enable)
+ reply.config.flags |= (1 << CFG_FLAG_AUTOADJUST_ENABLE);
+ send_message(&reply);
+ break;
+ } }
+}
+
+/* RX interrupt */
+ISR(USART_RXC_vect)
+{
+ uint8_t *rxbuf = (uint8_t *)&rx_msg;
+ int8_t err;
+ uint8_t data;
+
+ if (rx_msg_valid)
+ return;
+
+ while (1) {
+ err = usart_rx(&data);
+ if (err == -ENODATA)
+ break;
+ if (unlikely(err)) {
+ //TODO other error
+ data = 0;
+ }
+ rxbuf[rx_msg_count++] = data;
+ if (rx_msg_count == sizeof(struct remote_message)) {
+ rx_msg_count = 0;
+ mb();
+ rx_msg_valid = 1;
+ }
+ }
+}
+
+void print_pgm(const prog_char *str)
+{
+ struct remote_message msg;
+ uint8_t c, i;
+
+ do {
+ memset(&msg, 0, sizeof(msg));
+ msg.id = MSG_LOGMESSAGE;
+
+ for (i = 0; i < sizeof(msg.logmessage.str); i++) {
+ c = pgm_read_byte(str);
+ if (c == '\0')
+ break;
+ str++;
+ msg.logmessage.str[i] = c;
+ }
+
+ send_message(&msg);
+ } while (c != '\0');
+}
+
+/* Maintanance work. Called with IRQs enabled. */
+void remote_work(void)
+{
+ if (rx_msg_valid) {
+ handle_received_message();
+ mb();
+ rx_msg_valid = 0;
+ }
+}
+
+static void usart_init(void)
+{
+ uint8_t dummy;
+
+ /* Set baud rate */
+ UBRRL = lo8((CPU_HZ / 16 / BAUDRATE) * 2);
+ UBRRH = hi8((CPU_HZ / 16 / BAUDRATE) * 2) & ~(1 << URSEL);
+ UCSRA = (1 << U2X);
+ /* 8 Data bits, 2 Stop bits, Even parity */
+ UCSRC = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1) | (1 << UPM1) | (1 << USBS);
+ /* Enable transceiver and RX IRQs */
+ UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
+ /* Drain the RX buffer */
+ while (usart_rx(&dummy) != -ENODATA)
+ mb();
+}
+
+void remote_init(void)
+{
+ /* The remote tool depends on the exact size (and layout). */
+ BUILD_BUG_ON(sizeof(struct remote_message) != 38);
+
+ usart_init();
+}
diff --git a/pressure_control/firmware/remote.h b/pressure_control/firmware/remote.h
new file mode 100644
index 0000000..af18abf
--- /dev/null
+++ b/pressure_control/firmware/remote.h
@@ -0,0 +1,68 @@
+#ifndef REMOTE_H_
+#define REMOTE_H_
+
+#include <stdint.h>
+
+#include <avr/pgmspace.h>
+
+
+enum remote_message_id {
+ MSG_INVALID = 0, /* Discard me */
+ MSG_ERROR,
+ MSG_LOGMESSAGE,
+ MSG_PING,
+ MSG_PONG,
+ MSG_GET_CURRENT_PRESSURE,
+ MSG_CURRENT_PRESSURE,
+ MSG_GET_DESIRED_PRESSURE,
+ MSG_DESIRED_PRESSURE,
+ MSG_SET_DESIRED_PRESSURE,
+ MSG_GET_HYSTERESIS,
+ MSG_HYSTERESIS,
+ MSG_SET_HYSTERESIS,
+ MSG_GET_CONFIG_FLAGS,
+ MSG_CONFIG_FLAGS,
+ MSG_SET_CONFIG_FLAGS,
+};
+
+enum remote_message_error {
+ MSG_ERR_NONE = 0,
+ MSG_ERR_CHKSUM,
+};
+
+enum remote_message_config_flags {
+ CFG_FLAG_AUTOADJUST_ENABLE = 0,
+};
+
+struct remote_message {
+ uint8_t id;
+ uint8_t __padding0[3];
+
+ union {
+ struct {
+ uint8_t code;
+ } __attribute__((packed)) error;
+ struct {
+ char str[32];
+ } __attribute__((packed)) logmessage;
+ struct {
+ uint16_t mbar;
+ } __attribute__((packed)) pressure;
+ struct {
+ uint32_t flags;
+ } __attribute__((packed)) config;
+
+ uint8_t __padding1[32];
+ } __attribute__((packed));
+
+ uint16_t crc;
+} __attribute__((packed));
+
+
+void print_pgm(const prog_char *msg);
+#define print(string_literal) print_pgm(PSTR(string_literal))
+
+void remote_work(void);
+void remote_init(void);
+
+#endif /* REMOTE_H_ */
diff --git a/pressure_control/firmware/sensor.c b/pressure_control/firmware/sensor.c
index e663d7a..2ed36f3 100644
--- a/pressure_control/firmware/sensor.c
+++ b/pressure_control/firmware/sensor.c
@@ -19,10 +19,65 @@
*/
#include "sensor.h"
+#include "util.h"
#include <avr/io.h>
+#include <avr/interrupt.h>
+/*** The sensor enable signal ***/
+#define SENSOR_ENABLE_DDR DDRC
+#define SENSOR_ENABLE_PORT PORTC
+#define SENSOR_ENABLE_BIT 1
+
+
+static inline void sensor_enable(void)
+{
+ SENSOR_ENABLE_PORT |= (1 << SENSOR_ENABLE_BIT);
+}
+
+static inline void sensor_disable(void)
+{
+ SENSOR_ENABLE_PORT &= ~(1 << SENSOR_ENABLE_BIT);
+}
+
+ISR(ADC_vect)
+{
+ uint16_t val;
+
+ val = ADC;
+ sensor_disable();
+ //TODO process value
+ sensor_result(val);
+}
+
+static inline void adc_trigger(bool with_irq)
+{
+ /* Set the multiplexer to ADC-0, AVcc Ref. */
+ ADMUX = (1 << REFS0);
+ /* Start ADC with a prescaler of 128. That's a ADC freq
+ * of 125kHz on a 16MHz crystal. */
+ ADCSRA = (1 << ADEN) | (1 << ADSC) |
+ (1 << ADPS0) | (1 << ADPS1) | (1 << ADPS2) |
+ (with_irq ? (1 << ADIE) : 0);
+}
+
+void sensor_trigger_read(void)
+{
+ /* Enable the sensor and wait a dwell time for the
+ * sensor to stabilize. */
+ sensor_enable();
+ udelay(500);
+ /* Finally trigger the ADC conversion. */
+ adc_trigger(1);
+}
+
void sensor_init(void)
{
+ SENSOR_ENABLE_DDR |= (1 << SENSOR_ENABLE_BIT);
+ sensor_disable();
+ /* Discard the first ADC result. */
+ adc_trigger(0);
+ while (ADCSRA & (1 << ADSC))
+ mb();
}
diff --git a/pressure_control/firmware/sensor.h b/pressure_control/firmware/sensor.h
index dd03e29..a6230ad 100644
--- a/pressure_control/firmware/sensor.h
+++ b/pressure_control/firmware/sensor.h
@@ -4,6 +4,10 @@
#include <stdint.h>
+void sensor_trigger_read(void);
void sensor_init(void);
+/* Callback for sensor value reporting. */
+extern void sensor_result(uint16_t millibar_result_value);
+
#endif /* SENSOR_H_ */
diff --git a/pressure_control/firmware/util.c b/pressure_control/firmware/util.c
index 3cecc46..0056cbd 100644
--- a/pressure_control/firmware/util.c
+++ b/pressure_control/firmware/util.c
@@ -1,22 +1,26 @@
/*
- * Utility functions
+ * Utility functions.
*
- * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
+ * Copyright (C) 2008 Michael Buesch <mb@bu3sch.de>
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "util.h"
#include "calibration.h"
+#include <util/crc16.h>
#include <avr/io.h>
#include <avr/sleep.h>
@@ -76,3 +80,16 @@ void infinite_sleep(void)
while (1)
sleep_mode();
}
+
+uint16_t crc16_block_update(uint16_t crc, const void *_data, uint16_t size)
+{
+ const uint8_t *data = _data;
+
+ while (size) {
+ crc = _crc16_update(crc, *data);
+ data++;
+ size--;
+ }
+
+ return crc;
+}
diff --git a/pressure_control/firmware/util.h b/pressure_control/firmware/util.h
index 11c5f27..0c37990 100644
--- a/pressure_control/firmware/util.h
+++ b/pressure_control/firmware/util.h
@@ -72,4 +72,7 @@ static inline void irq_restore(uint8_t sreg_flags)
#define irqs_disabled() (!(SREG & (1 << SREG_I)))
+
+uint16_t crc16_block_update(uint16_t crc, const void *data, uint16_t size);
+
#endif /* UTIL_H_ */
bues.ch cgit interface