$(shell mkdir -p dist >/dev/null)
$(shell mkdir -p build >/dev/null)
$(shell mkdir -p sim >/dev/null)
+$(shell mkdir -p sim/build >/dev/null)
NAME="test_2024-07-23_nano-5v"
+
SRC= $(wildcard src/*.c src/*.cpp src/*/*.cpp)
-OBJ = $(SRC:src/%.c=build/%.o)
-OBJ_SIM = $(SRC:src/%.c=sim/%.o)
+OBJ_CPP = $(SRC:src/%.cpp=build/%.o)
+OBJ = $(OBJ_CPP:src/%.c=build/%.o)
+OBJ_SIM_CPP = $(SRC:src/%.cpp=sim/build/%.o)
+OBJ_SIM = $(OBJ_SIM_CPP:src/%.c=sim/build/%.o)
DEVICE=atmega328p
CC= avr-g++
-CFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=16000000 -c
-LFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=16000000 -Wl,-u,vfprintf -lprintf_flt -lm
+CFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=12000000 -c
+LFLAGS= -Wall -mmcu=$(DEVICE) -Os -DF_CPU=12000000 -Wl,-u,vfprintf -lprintf_flt -lm
-CFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=16000000 -g -c
-LFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=16000000 -g -Wl,-u,vfprintf -lprintf_flt -lm
+CFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=12000000 -g -c
+LFLAGS_SIM= -Wall -mmcu=$(DEVICE) -Og -DF_CPU=12000000 -g -Wl,-u,vfprintf -lprintf_flt -lm
all: dist/$(NAME).elf dist/$(NAME).s dist/$(NAME).hex sim/$(NAME).elf sim/$(NAME).s info
-
+
+dbg:
+ @echo "OBJ_CPP" $(OBJ_CPP)
+ @echo "OBJ" $(OBJ)
+ @echo "OBJ_SIM_CPP" $(OBJ_SIM_CPP)
+ @echo "OBJ_SIM" $(OBJ_SIM)
+
info:
@echo
@avr-size --mcu=$(DEVICE) --format=avr dist/$(NAME).elf
build/%.o: src/%.c
+ @mkdir -p $(dir $@)
$(CC) $(CFLAGS) -o $@ $<
-sim/%.o: src/%.c
+build/%.o: src/%.cpp
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS) -o $@ $<
+
+sim/build/%.o: src/%.c
+ @mkdir -p $(dir $@)
+ $(CC) $(CFLAGS_SIM) -o $@ $<
+
+sim/build/%.o: src/%.cpp
+ @mkdir -p $(dir $@)
$(CC) $(CFLAGS_SIM) -o $@ $<
sim/%.s: sim/%.elf
gdb: sim/$(NAME).elf
avr-gdb $<
-isp-328p:
- avrdude -c usbasp -p m328p
+isp-644p:
+ avrdude -c usbasp -p m644p
-isp-flash-328p: dist/$(NAME).elf all
- avrdude -c usbasp -p m328p -e -U flash:w:$<
+isp-flash-644p: dist/$(NAME).elf all
+ avrdude -c usbasp -p m644p -e -U flash:w:$<
-flash-328p: dist/$(NAME).elf all
- avrdude -c arduino -p m328p -P /dev/ttyUSB0 -b 115200 -e -U flash:w:$<
+flash-644p: dist/$(NAME).elf all
+ avrdude -c arduino -p m644p -P /dev/ttyUSB0 -b 115200 -e -U flash:w:$<
picocom:
# picocom sends CR for ENTER -> convert cr (\r) to lf (\n)
picocom -b 115200 --omap crlf /dev/ttyUSB0
-isp-fuse-328p:
- avrdude -c usbasp -p m328p -U lfuse:w:0x62:m -U hfuse:w:0xD9:m -U efuse:w:0xFF:m -U lock:w:0xFF:m
+isp-fuse-644p:
+ avrdude -c usbasp -p m644p -U lfuse:w:0xFF:m -U hfuse:w:0xD9:m -U efuse:w:0xFF:m -U lock:w:0xFF:m
clean:
@rm -r dist
--- /dev/null
+../../nano-644/test_2024-07-23/src
\ No newline at end of file
+++ /dev/null
-#include "bme280.h"
-#include <util/delay.h>
-#include <stdio.h>
-
-Adafruit_BME280 theBME280;
-Adafruit_BME280_Temp bm280TempSensor;
-Adafruit_BME280_Pressure bm280PressureSensor;
-Adafruit_BME280_Humidity bm280HumiditySensor;
-
-Adafruit_BME280::Adafruit_BME280() {
- static I2cMaster i2cDevice;
- t_fine_adjust = 0;
- temp_sensor = &bm280TempSensor;
- pressure_sensor = &bm280PressureSensor;
- humidity_sensor = &bm280HumiditySensor;
- i2c_dev = &i2cDevice;
-}
-
-bool Adafruit_BME280::begin (uint8_t addr) {
- if (!i2c_dev->begin(addr)) {
- return false;
- }
- return init();
-}
-
-bool Adafruit_BME280::init() {
- _sensorID = read8(BME280_REGISTER_CHIPID);
- if (_sensorID != 0x60) {
- return false;
- }
- write8(BME280_REGISTER_SOFTRESET, 0xB6);
- _delay_ms(10); // wait for chip to wake up.
-
- // if chip is still reading calibration, delay
- while (isReadingCalibration()) {
- _delay_ms(10);
- }
-
- readCoefficients(); // read trimming parameters, see DS 4.2.2
- setSampling(); // use defaults
- _delay_ms(100);
-
- return true;
-}
-
-/*!
- * @brief setup sensor with given parameters / settings
- *
- * This is simply a overload to the normal begin()-function, so SPI users
- * don't get confused about the library requiring an address.
- * @param mode the power mode to use for the sensor
- * @param tempSampling the temp samping rate to use
- * @param pressSampling the pressure sampling rate to use
- * @param humSampling the humidity sampling rate to use
- * @param filter the filter mode to use
- * @param duration the standby duration to use
- */
-void Adafruit_BME280::setSampling(sensor_mode mode,
- sensor_sampling tempSampling,
- sensor_sampling pressSampling,
- sensor_sampling humSampling,
- sensor_filter filter,
- standby_duration duration) {
- _measReg.mode = mode;
- _measReg.osrs_t = tempSampling;
- _measReg.osrs_p = pressSampling;
-
- _humReg.osrs_h = humSampling;
- _configReg.filter = filter;
- _configReg.t_sb = duration;
- _configReg.spi3w_en = 0;
-
- // making sure sensor is in sleep mode before setting configuration
- // as it otherwise may be ignored
- write8(BME280_REGISTER_CONTROL, MODE_SLEEP);
-
- // you must make sure to also set REGISTER_CONTROL after setting the
- // CONTROLHUMID register, otherwise the values won't be applied (see
- // DS 5.4.3)
- write8(BME280_REGISTER_CONTROLHUMID, _humReg.get());
- write8(BME280_REGISTER_CONFIG, _configReg.get());
- write8(BME280_REGISTER_CONTROL, _measReg.get());
-}
-
-/*!
- * @brief Writes an 8 bit value over I2C or SPI
- * @param reg the register address to write to
- * @param value the value to write to the register
- */
-void Adafruit_BME280::write8(byte reg, byte value) {
- byte buffer[2];
- buffer[1] = value;
- if (i2c_dev) {
- buffer[0] = reg;
- i2c_dev->write(buffer, 2);
- }
-}
-
-/*!
- * @brief Reads an 8 bit value over I2C or SPI
- * @param reg the register address to read from
- * @returns the data byte read from the device
- */
-uint8_t Adafruit_BME280::read8(byte reg) {
- uint8_t buffer[1];
- if (i2c_dev) {
- buffer[0] = uint8_t(reg);
- i2c_dev->write_then_read(buffer, 1, buffer, 1);
- }
- return buffer[0];
-}
-
-/*!
- * @brief Reads a 16 bit value over I2C or SPI
- * @param reg the register address to read from
- * @returns the 16 bit data value read from the device
- */
-uint16_t Adafruit_BME280::read16(byte reg) {
- uint8_t buffer[2];
-
- if (i2c_dev) {
- buffer[0] = uint8_t(reg);
- i2c_dev->write_then_read(buffer, 1, buffer, 2);
- }
- return uint16_t(buffer[0]) << 8 | uint16_t(buffer[1]);
-}
-
-/*!
- * @brief Reads a signed 16 bit little endian value over I2C or SPI
- * @param reg the register address to read from
- * @returns the 16 bit data value read from the device
- */
-uint16_t Adafruit_BME280::read16_LE(byte reg) {
- uint16_t temp = read16(reg);
- return (temp >> 8) | (temp << 8);
-}
-
-/*!
- * @brief Reads a signed 16 bit value over I2C or SPI
- * @param reg the register address to read from
- * @returns the 16 bit data value read from the device
- */
-int16_t Adafruit_BME280::readS16(byte reg) { return (int16_t)read16(reg); }
-
-/*!
- * @brief Reads a signed little endian 16 bit value over I2C or SPI
- * @param reg the register address to read from
- * @returns the 16 bit data value read from the device
- */
-int16_t Adafruit_BME280::readS16_LE(byte reg) {
- return (int16_t)read16_LE(reg);
-}
-
-/*!
- * @brief Reads a 24 bit value over I2C
- * @param reg the register address to read from
- * @returns the 24 bit data value read from the device
- */
-uint32_t Adafruit_BME280::read24(byte reg) {
- uint8_t buffer[3];
-
- if (i2c_dev) {
- buffer[0] = uint8_t(reg);
- i2c_dev->write_then_read(buffer, 1, buffer, 3);
- }
- return uint32_t(buffer[0]) << 16 | uint32_t(buffer[1]) << 8 |
- uint32_t(buffer[2]);
-}
-
-/*!
- * @brief Take a new measurement (only possible in forced mode)
- @returns true in case of success else false
- */
-bool Adafruit_BME280::takeForcedMeasurement(void) {
- bool return_value = false;
- // If we are in forced mode, the BME sensor goes back to sleep after each
- // measurement and we need to set it to forced mode once at this point, so
- // it will take the next measurement and then return to sleep again.
- // In normal mode simply does new measurements periodically.
- if (_measReg.mode == MODE_FORCED) {
- return_value = true;
- // set to forced mode, i.e. "take next measurement"
- write8(BME280_REGISTER_CONTROL, _measReg.get());
- // Store current time to measure the timeout
- uint32_t timeout_start = millis();
- // wait until measurement has been completed, otherwise we would read the
- // the values from the last measurement or the timeout occurred after 2 sec.
- while (read8(BME280_REGISTER_STATUS) & 0x08) {
- // In case of a timeout, stop the while loop
- if ((millis() - timeout_start) > 2000) {
- return_value = false;
- break;
- }
- _delay_ms(1);
- }
- }
- return return_value;
-}
-
-/*!
- * @brief Reads the factory-set coefficients
- */
-void Adafruit_BME280::readCoefficients(void) {
- _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1);
- _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2);
- _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3);
-
- _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1);
- _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2);
- _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3);
- _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4);
- _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5);
- _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6);
- _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7);
- _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8);
- _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9);
-
- _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1);
- _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2);
- _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3);
- _bme280_calib.dig_H4 = ((int8_t)read8(BME280_REGISTER_DIG_H4) << 4) |
- (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF);
- _bme280_calib.dig_H5 = ((int8_t)read8(BME280_REGISTER_DIG_H5 + 1) << 4) |
- (read8(BME280_REGISTER_DIG_H5) >> 4);
- _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6);
-}
-
-/*!
- * @brief return true if chip is busy reading cal data
- * @returns true if reading calibration, false otherwise
- */
-bool Adafruit_BME280::isReadingCalibration(void) {
- uint8_t const rStatus = read8(BME280_REGISTER_STATUS);
-
- return (rStatus & (1 << 0)) != 0;
-}
-
-/*!
- * @brief Returns the temperature from the sensor
- * @returns the temperature read from the device
- */
-float Adafruit_BME280::readTemperature(void) {
- int32_t var1, var2;
-
- int32_t adc_T = read24(BME280_REGISTER_TEMPDATA);
- if (adc_T == 0x800000) // value in case temp measurement was disabled
- return NAN;
- adc_T >>= 4;
-
- var1 = (int32_t)((adc_T / 8) - ((int32_t)_bme280_calib.dig_T1 * 2));
- var1 = (var1 * ((int32_t)_bme280_calib.dig_T2)) / 2048;
- var2 = (int32_t)((adc_T / 16) - ((int32_t)_bme280_calib.dig_T1));
- var2 = (((var2 * var2) / 4096) * ((int32_t)_bme280_calib.dig_T3)) / 16384;
-
- t_fine = var1 + var2 + t_fine_adjust;
-
- int32_t T = (t_fine * 5 + 128) / 256;
-
- return (float)T / 100;
-}
-
-/*!
- * @brief Returns the pressure from the sensor
- * @returns the pressure value (in Pascal) read from the device
- */
-float Adafruit_BME280::readPressure(void) {
- int64_t var1, var2, var3, var4;
-
- readTemperature(); // must be done first to get t_fine
-
- int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA);
- if (adc_P == 0x800000) // value in case pressure measurement was disabled
- return NAN;
- adc_P >>= 4;
-
- var1 = ((int64_t)t_fine) - 128000;
- var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6;
- var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) * 131072);
- var2 = var2 + (((int64_t)_bme280_calib.dig_P4) * 34359738368);
- var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) / 256) +
- ((var1 * ((int64_t)_bme280_calib.dig_P2) * 4096));
- var3 = ((int64_t)1) * 140737488355328;
- var1 = (var3 + var1) * ((int64_t)_bme280_calib.dig_P1) / 8589934592;
-
- if (var1 == 0) {
- return 0; // avoid exception caused by division by zero
- }
-
- var4 = 1048576 - adc_P;
- var4 = (((var4 * 2147483648UL) - var2) * 3125) / var1;
- var1 = (((int64_t)_bme280_calib.dig_P9) * (var4 / 8192) * (var4 / 8192)) /
- 33554432;
- var2 = (((int64_t)_bme280_calib.dig_P8) * var4) / 524288;
- var4 = ((var4 + var1 + var2) / 256) + (((int64_t)_bme280_calib.dig_P7) * 16);
-
- float P = var4 / 256.0;
-
- return P;
-}
-
-/*!
- * @brief Returns the humidity from the sensor
- * @returns the humidity value read from the device
- */
-float Adafruit_BME280::readHumidity(void) {
- int32_t var1, var2, var3, var4, var5;
-
- readTemperature(); // must be done first to get t_fine
-
- int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
- if (adc_H == 0x8000) // value in case humidity measurement was disabled
- return NAN;
-
- var1 = t_fine - ((int32_t)76800);
- var2 = (int32_t)(adc_H * 16384);
- var3 = (int32_t)(((int32_t)_bme280_calib.dig_H4) * 1048576);
- var4 = ((int32_t)_bme280_calib.dig_H5) * var1;
- var5 = (((var2 - var3) - var4) + (int32_t)16384) / 32768;
- var2 = (var1 * ((int32_t)_bme280_calib.dig_H6)) / 1024;
- var3 = (var1 * ((int32_t)_bme280_calib.dig_H3)) / 2048;
- var4 = ((var2 * (var3 + (int32_t)32768)) / 1024) + (int32_t)2097152;
- var2 = ((var4 * ((int32_t)_bme280_calib.dig_H2)) + 8192) / 16384;
- var3 = var5 * var2;
- var4 = ((var3 / 32768) * (var3 / 32768)) / 128;
- var5 = var3 - ((var4 * ((int32_t)_bme280_calib.dig_H1)) / 16);
- var5 = (var5 < 0 ? 0 : var5);
- var5 = (var5 > 419430400 ? 419430400 : var5);
- uint32_t H = (uint32_t)(var5 / 4096);
-
- return (float)H / 1024.0;
-}
-
-/*!
- * Calculates the altitude (in meters) from the specified atmospheric
- * pressure (in hPa), and sea-level pressure (in hPa).
- * @param seaLevel Sea-level pressure in hPa
- * @returns the altitude value read from the device
- */
-float Adafruit_BME280::readAltitude(float seaLevel) {
- // Equation taken from BMP180 datasheet (page 16):
- // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
-
- // Note that using the equation from wikipedia can give bad results
- // at high altitude. See this thread for more information:
- // http://forums.adafruit.com/viewtopic.php?f=22&t=58064
-
- float atmospheric = readPressure() / 100.0F;
- return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903));
-}
-
-/*!
- * Calculates the pressure at sea level (in hPa) from the specified
- * altitude (in meters), and atmospheric pressure (in hPa).
- * @param altitude Altitude in meters
- * @param atmospheric Atmospheric pressure in hPa
- * @returns the pressure at sea level (in hPa) from the specified altitude
- */
-float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) {
- // Equation taken from BMP180 datasheet (page 17):
- // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
-
- // Note that using the equation from wikipedia can give bad results
- // at high altitude. See this thread for more information:
- // http://forums.adafruit.com/viewtopic.php?f=22&t=58064
-
- return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255);
-}
-
-/*!
- * Returns Sensor ID found by init() for diagnostics
- * @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280
- */
-uint32_t Adafruit_BME280::sensorID(void) { return _sensorID; }
-
-/*!
- * Returns the current temperature compensation value in degrees Celsius
- * @returns the current temperature compensation value in degrees Celsius
- */
-float Adafruit_BME280::getTemperatureCompensation(void) {
- return float((t_fine_adjust * 5) >> 8) / 100.0;
-};
-
-/*!
- * Sets a value to be added to each temperature reading. This adjusted
- * temperature is used in pressure and humidity readings.
- * @param adjustment Value to be added to each temperature reading in Celsius
- */
-void Adafruit_BME280::setTemperatureCompensation(float adjustment) {
- // convert the value in C into and adjustment to t_fine
- t_fine_adjust = ((int32_t(adjustment * 100) << 8)) / 5;
-};
-
-
-/**************************************************************************/
-/*!
- @brief Gets the sensor_t data for the BME280's temperature sensor
-*/
-/**************************************************************************/
-void Adafruit_BME280_Temp::getSensor(sensor_t *sensor) {
- /* Clear the sensor_t object */
- memset(sensor, 0, sizeof(sensor_t));
-
- /* Insert the sensor name in the fixed length char array */
- strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1);
- sensor->name[sizeof(sensor->name) - 1] = 0;
- sensor->version = 1;
- sensor->sensor_id = _sensorID;
- sensor->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
- sensor->min_delay = 0;
- sensor->min_value = -40.0; /* Temperature range -40 ~ +85 C */
- sensor->max_value = +85.0;
- sensor->resolution = 0.01; /* 0.01 C */
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the temperature as a standard sensor event
- @param event Sensor event object that will be populated
- @returns True
-*/
-/**************************************************************************/
-bool Adafruit_BME280_Temp::getEvent(sensors_event_t *event) {
- /* Clear the event */
- memset(event, 0, sizeof(sensors_event_t));
-
- event->version = sizeof(sensors_event_t);
- event->sensor_id = _sensorID;
- event->type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
- event->timestamp = millis();
- event->temperature = theBME280.readTemperature();
- return true;
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the sensor_t data for the BME280's pressure sensor
-*/
-/**************************************************************************/
-void Adafruit_BME280_Pressure::getSensor(sensor_t *sensor) {
- /* Clear the sensor_t object */
- memset(sensor, 0, sizeof(sensor_t));
-
- /* Insert the sensor name in the fixed length char array */
- strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1);
- sensor->name[sizeof(sensor->name) - 1] = 0;
- sensor->version = 1;
- sensor->sensor_id = _sensorID;
- sensor->type = SENSOR_TYPE_PRESSURE;
- sensor->min_delay = 0;
- sensor->min_value = 300.0; /* 300 ~ 1100 hPa */
- sensor->max_value = 1100.0;
- sensor->resolution = 0.012; /* 0.12 hPa relative */
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the pressure as a standard sensor event
- @param event Sensor event object that will be populated
- @returns True
-*/
-/**************************************************************************/
-bool Adafruit_BME280_Pressure::getEvent(sensors_event_t *event) {
- /* Clear the event */
- memset(event, 0, sizeof(sensors_event_t));
-
- event->version = sizeof(sensors_event_t);
- event->sensor_id = _sensorID;
- event->type = SENSOR_TYPE_PRESSURE;
- event->timestamp = millis();
- event->pressure = theBME280.readPressure() / 100; // convert Pa to hPa
- return true;
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the sensor_t data for the BME280's humidity sensor
-*/
-/**************************************************************************/
-void Adafruit_BME280_Humidity::getSensor(sensor_t *sensor) {
- /* Clear the sensor_t object */
- memset(sensor, 0, sizeof(sensor_t));
-
- /* Insert the sensor name in the fixed length char array */
- strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1);
- sensor->name[sizeof(sensor->name) - 1] = 0;
- sensor->version = 1;
- sensor->sensor_id = _sensorID;
- sensor->type = SENSOR_TYPE_RELATIVE_HUMIDITY;
- sensor->min_delay = 0;
- sensor->min_value = 0;
- sensor->max_value = 100; /* 0 - 100 % */
- sensor->resolution = 3; /* 3% accuracy */
-}
-
-/**************************************************************************/
-/*!
- @brief Gets the humidity as a standard sensor event
- @param event Sensor event object that will be populated
- @returns True
-*/
-/**************************************************************************/
-bool Adafruit_BME280_Humidity::getEvent(sensors_event_t *event) {
- /* Clear the event */
- memset(event, 0, sizeof(sensors_event_t));
-
- event->version = sizeof(sensors_event_t);
- event->sensor_id = _sensorID;
- event->type = SENSOR_TYPE_RELATIVE_HUMIDITY;
- event->timestamp = millis();
- event->relative_humidity = theBME280.readHumidity();
- return true;
-}
+++ /dev/null
-// https://github.com/adafruit/Adafruit_BME280_Library
-
-/*!
- * @file Adafruit_BME280.h
- *
- * Designed specifically to work with the Adafruit BME280 Breakout
- * ----> http://www.adafruit.com/products/2650
- *
- * These sensors use I2C or SPI to communicate, 2 or 4 pins are required
- * to interface.
- *
- * Adafruit invests time and resources providing this open source code,
- * please support Adafruit and open-source hardware by purchasing
- * products from Adafruit!
- *
- * Written by Kevin "KTOWN" Townsend for Adafruit Industries.
- *
- * BSD license, all text here must be included in any redistribution.
- * See the LICENSE file for details.
- *
- */
-
-#ifndef __BME280_H__
-#define __BME280_H__
-
-// #include "Arduino.h"
-
-// #include <Adafruit_I2CDevice.h>
-// #include <Adafruit_SPIDevice.h>
-// #include <Adafruit_Sensor.h>
-
-
-#include "../i2cmaster.hpp"
-#include "../main.hpp"
-#define byte uint8_t
-
-
-
-#include <stdint.h>
-#include <string.h>
-#include "sensor.h"
-
-/*!
- * @brief default I2C address
- */
-#define BME280_ADDRESS (0x77) // Primary I2C Address
- /*!
- * @brief alternate I2C address
- */
-#define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address
-
-/*!
- * @brief Register addresses
- */
-enum {
- BME280_REGISTER_DIG_T1 = 0x88,
- BME280_REGISTER_DIG_T2 = 0x8A,
- BME280_REGISTER_DIG_T3 = 0x8C,
-
- BME280_REGISTER_DIG_P1 = 0x8E,
- BME280_REGISTER_DIG_P2 = 0x90,
- BME280_REGISTER_DIG_P3 = 0x92,
- BME280_REGISTER_DIG_P4 = 0x94,
- BME280_REGISTER_DIG_P5 = 0x96,
- BME280_REGISTER_DIG_P6 = 0x98,
- BME280_REGISTER_DIG_P7 = 0x9A,
- BME280_REGISTER_DIG_P8 = 0x9C,
- BME280_REGISTER_DIG_P9 = 0x9E,
-
- BME280_REGISTER_DIG_H1 = 0xA1,
- BME280_REGISTER_DIG_H2 = 0xE1,
- BME280_REGISTER_DIG_H3 = 0xE3,
- BME280_REGISTER_DIG_H4 = 0xE4,
- BME280_REGISTER_DIG_H5 = 0xE5,
- BME280_REGISTER_DIG_H6 = 0xE7,
-
- BME280_REGISTER_CHIPID = 0xD0,
- BME280_REGISTER_VERSION = 0xD1,
- BME280_REGISTER_SOFTRESET = 0xE0,
-
- BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0
-
- BME280_REGISTER_CONTROLHUMID = 0xF2,
- BME280_REGISTER_STATUS = 0XF3,
- BME280_REGISTER_CONTROL = 0xF4,
- BME280_REGISTER_CONFIG = 0xF5,
- BME280_REGISTER_PRESSUREDATA = 0xF7,
- BME280_REGISTER_TEMPDATA = 0xFA,
- BME280_REGISTER_HUMIDDATA = 0xFD
-};
-
-/**************************************************************************/
-/*!
- @brief calibration data
-*/
-/**************************************************************************/
-typedef struct {
- uint16_t dig_T1; ///< temperature compensation value
- int16_t dig_T2; ///< temperature compensation value
- int16_t dig_T3; ///< temperature compensation value
-
- uint16_t dig_P1; ///< pressure compensation value
- int16_t dig_P2; ///< pressure compensation value
- int16_t dig_P3; ///< pressure compensation value
- int16_t dig_P4; ///< pressure compensation value
- int16_t dig_P5; ///< pressure compensation value
- int16_t dig_P6; ///< pressure compensation value
- int16_t dig_P7; ///< pressure compensation value
- int16_t dig_P8; ///< pressure compensation value
- int16_t dig_P9; ///< pressure compensation value
-
- uint8_t dig_H1; ///< humidity compensation value
- int16_t dig_H2; ///< humidity compensation value
- uint8_t dig_H3; ///< humidity compensation value
- int16_t dig_H4; ///< humidity compensation value
- int16_t dig_H5; ///< humidity compensation value
- int8_t dig_H6; ///< humidity compensation value
-} bme280_calib_data;
-/*=========================================================================*/
-
-class Adafruit_BME280;
-
-/** Adafruit Unified Sensor interface for temperature component of BME280 */
-class Adafruit_BME280_Temp : public Adafruit_Sensor {
-public:
- /** @brief Create an Adafruit_Sensor compatible object for the temp sensor
- @param parent A pointer to the BME280 class */
- Adafruit_BME280_Temp() { _sensorID = 280; }
- bool getEvent(sensors_event_t *);
- void getSensor(sensor_t *);
-
-private:
- int _sensorID;
-};
-
-/** Adafruit Unified Sensor interface for pressure component of BME280 */
-class Adafruit_BME280_Pressure : public Adafruit_Sensor {
-public:
- /** @brief Create an Adafruit_Sensor compatible object for the pressure sensor
- @param parent A pointer to the BME280 class */
- Adafruit_BME280_Pressure() { _sensorID = 280; }
- bool getEvent(sensors_event_t *);
- void getSensor(sensor_t *);
-
-private:
- int _sensorID;
-};
-
-/** Adafruit Unified Sensor interface for humidity component of BME280 */
-class Adafruit_BME280_Humidity : public Adafruit_Sensor {
-public:
- /** @brief Create an Adafruit_Sensor compatible object for the humidity sensor
- @param parent A pointer to the BME280 class */
- Adafruit_BME280_Humidity() { _sensorID = 280;}
- bool getEvent(sensors_event_t *);
- void getSensor(sensor_t *);
-
-private:
- int _sensorID;
-};
-
-/**************************************************************************/
-/*!
- @brief Class that stores state and functions for interacting with BME280 IC
-*/
-/**************************************************************************/
-class Adafruit_BME280 {
-public:
- /**************************************************************************/
- /*!
- @brief sampling rates
- */
- /**************************************************************************/
- enum sensor_sampling {
- SAMPLING_NONE = 0b000,
- SAMPLING_X1 = 0b001,
- SAMPLING_X2 = 0b010,
- SAMPLING_X4 = 0b011,
- SAMPLING_X8 = 0b100,
- SAMPLING_X16 = 0b101
- };
-
- /**************************************************************************/
- /*!
- @brief power modes
- */
- /**************************************************************************/
- enum sensor_mode {
- MODE_SLEEP = 0b00,
- MODE_FORCED = 0b01,
- MODE_NORMAL = 0b11
- };
-
- /**************************************************************************/
- /*!
- @brief filter values
- */
- /**************************************************************************/
- enum sensor_filter {
- FILTER_OFF = 0b000,
- FILTER_X2 = 0b001,
- FILTER_X4 = 0b010,
- FILTER_X8 = 0b011,
- FILTER_X16 = 0b100
- };
-
- /**************************************************************************/
- /*!
- @brief standby duration in ms
- */
- /**************************************************************************/
- enum standby_duration {
- STANDBY_MS_0_5 = 0b000,
- STANDBY_MS_10 = 0b110,
- STANDBY_MS_20 = 0b111,
- STANDBY_MS_62_5 = 0b001,
- STANDBY_MS_125 = 0b010,
- STANDBY_MS_250 = 0b011,
- STANDBY_MS_500 = 0b100,
- STANDBY_MS_1000 = 0b101
- };
-
- // constructors
- Adafruit_BME280();
-
- bool begin(uint8_t addr = BME280_ADDRESS);
- bool init();
-
- void setSampling(sensor_mode mode = MODE_NORMAL,
- sensor_sampling tempSampling = SAMPLING_X16,
- sensor_sampling pressSampling = SAMPLING_X16,
- sensor_sampling humSampling = SAMPLING_X16,
- sensor_filter filter = FILTER_OFF,
- standby_duration duration = STANDBY_MS_0_5);
-
- bool takeForcedMeasurement(void);
- float readTemperature(void);
- float readPressure(void);
- float readHumidity(void);
-
- float readAltitude(float seaLevel);
- float seaLevelForAltitude(float altitude, float pressure);
- uint32_t sensorID(void);
-
- float getTemperatureCompensation(void);
- void setTemperatureCompensation(float);
-
-protected:
- I2cMaster *i2c_dev = NULL; ///< Pointer to I2C bus interface
- // Adafruit_SPIDevice *spi_dev = NULL; ///< Pointer to SPI bus interface
-
- Adafruit_BME280_Temp *temp_sensor;
- Adafruit_BME280_Pressure *pressure_sensor;
- Adafruit_BME280_Humidity *humidity_sensor;
-
- void readCoefficients(void);
- bool isReadingCalibration(void);
-
- void write8(byte reg, byte value);
- uint8_t read8(byte reg);
- uint16_t read16(byte reg);
- uint32_t read24(byte reg);
- int16_t readS16(byte reg);
- uint16_t read16_LE(byte reg); // little endian
- int16_t readS16_LE(byte reg); // little endian
-
- uint8_t _i2caddr; //!< I2C addr for the TwoWire interface
- int32_t _sensorID; //!< ID of the BME Sensor
- int32_t t_fine; //!< temperature with high resolution, stored as an attribute
- //!< as this is used for temperature compensation reading
- //!< humidity and pressure
-
- int32_t t_fine_adjust; //!< add to compensate temp readings and in turn
- //!< to pressure and humidity readings
-
- bme280_calib_data _bme280_calib; //!< here calibration data is stored
-
- /**************************************************************************/
- /*!
- @brief config register
- */
- /**************************************************************************/
- struct config {
- // inactive duration (standby time) in normal mode
- // 000 = 0.5 ms
- // 001 = 62.5 ms
- // 010 = 125 ms
- // 011 = 250 ms
- // 100 = 500 ms
- // 101 = 1000 ms
- // 110 = 10 ms
- // 111 = 20 ms
- unsigned int t_sb : 3; ///< inactive duration (standby time) in normal mode
-
- // filter settings
- // 000 = filter off
- // 001 = 2x filter
- // 010 = 4x filter
- // 011 = 8x filter
- // 100 and above = 16x filter
- unsigned int filter : 3; ///< filter settings
-
- // unused - don't set
- unsigned int none : 1; ///< unused - don't set
- unsigned int spi3w_en : 1; ///< unused - don't set
-
- /// @return combined config register
- unsigned int get() { return (t_sb << 5) | (filter << 2) | spi3w_en; }
- };
- config _configReg; //!< config register object
-
- /**************************************************************************/
- /*!
- @brief ctrl_meas register
- */
- /**************************************************************************/
- struct ctrl_meas {
- // temperature oversampling
- // 000 = skipped
- // 001 = x1
- // 010 = x2
- // 011 = x4
- // 100 = x8
- // 101 and above = x16
- unsigned int osrs_t : 3; ///< temperature oversampling
-
- // pressure oversampling
- // 000 = skipped
- // 001 = x1
- // 010 = x2
- // 011 = x4
- // 100 = x8
- // 101 and above = x16
- unsigned int osrs_p : 3; ///< pressure oversampling
-
- // device mode
- // 00 = sleep
- // 01 or 10 = forced
- // 11 = normal
- unsigned int mode : 2; ///< device mode
-
- /// @return combined ctrl register
- unsigned int get() { return (osrs_t << 5) | (osrs_p << 2) | mode; }
- };
- ctrl_meas _measReg; //!< measurement register object
-
- /**************************************************************************/
- /*!
- @brief ctrl_hum register
- */
- /**************************************************************************/
- struct ctrl_hum {
- /// unused - don't set
- unsigned int none : 5;
-
- // pressure oversampling
- // 000 = skipped
- // 001 = x1
- // 010 = x2
- // 011 = x4
- // 100 = x8
- // 101 and above = x16
- unsigned int osrs_h : 3; ///< pressure oversampling
-
- /// @return combined ctrl hum register
- unsigned int get() { return (osrs_h); }
- };
- ctrl_hum _humReg; //!< hum register object
-};
-
-extern Adafruit_BME280 theBME280;
-
-#endif
+++ /dev/null
-/*
- ScioSense_ENS160.h - Library for the ENS160 sensor with I2C interface from ScioSense
- 2023 Mar 23 v6 Christoph Friese Bugfix measurement routine, prepare next release
- 2021 Nov 25 v5 Martin Herold Custom mode timing fixed
- 2021 Feb 04 v4 Giuseppe de Pinto Custom mode fixed
- 2020 Apr 06 v3 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams
- 2020 Feb 15 v2 Giuseppe Pasetti Corrected firmware flash option
- 2019 May 05 v1 Christoph Friese Created
- based on application note "ENS160 Software Integration.pdf" rev 0.01
-*/
-
-#include "ens160.h"
-#include "math.h"
-#include <util/delay.h>
-#include <stdio.h>
-#include <avr/io.h>
-
-ScioSense_ENS160::ScioSense_ENS160 () {
- _revENS16x = 0;
-
- //Isotherm, HP0 252°C / HP1 350°C / HP2 250°C / HP3 324°C / measure every 1008ms
- _seq_steps[0][0] = 0x7c;
- _seq_steps[0][1] = 0x0a;
- _seq_steps[0][2] = 0x7e;
- _seq_steps[0][3] = 0xaf;
- _seq_steps[0][4] = 0xaf;
- _seq_steps[0][5] = 0xa2;
- _seq_steps[0][6] = 0x00;
- _seq_steps[0][7] = 0x80;
-}
-
-bool ScioSense_ENS160::begin () {
- i2cDevice.begin(ENS160_I2CADDR_1);
- _delay_ms(ENS160_BOOTING);
- if (reset()) {
- if (checkPartID()) {
- if (setMode(ENS160_OPMODE_IDLE)) {
- if (clearCommand()) {
- if (getFirmware()) {
- return true;
- }
- }
- }
- }
- }
- return false;
-
-}
-
-bool ScioSense_ENS160::write8 (byte reg, byte value) {
- byte buffer[2];
- buffer[1] = value;
- buffer[0] = reg;
- return i2cDevice.write(buffer, 2);
-}
-
-bool ScioSense_ENS160::read8 (byte reg, byte *value) {
- uint8_t buffer[1];
- buffer[0] = uint8_t(reg);
- return i2cDevice.write_then_read(buffer, 1, value, 1);
-}
-
-bool ScioSense_ENS160::read16 (byte reg, uint16_t *value) {
- uint8_t buffer[1];
- buffer[0] = uint8_t(reg);
- return i2cDevice.write_then_read(buffer, 1, (uint8_t *)value, 2);
-}
-
-bool ScioSense_ENS160::read16LE (byte reg, uint16_t *value) {
- uint16_t tmp;
- if (read16(reg, &tmp)) {
- *value = ((tmp & 0xff) << 8) | (tmp >> 8);
- return true;
- }
- return false;
-}
-
-bool ScioSense_ENS160::readBytes (byte reg, uint8_t *bytes, uint8_t len) {
- uint8_t buffer[1];
- buffer[0] = uint8_t(reg);
- return i2cDevice.write_then_read(buffer, 1, buffer, len);
-}
-
-
-// Sends a reset to the ENS160. Returns false on I2C problems.
-bool ScioSense_ENS160::reset () {
- if (write8(ENS160_REG_OPMODE, ENS160_OPMODE_RESET)) {
- _delay_ms(ENS160_BOOTING);
- return true;
- }
- _delay_ms(ENS160_BOOTING);
- return false;
-}
-
-// Reads the part ID and confirms valid sensor
-bool ScioSense_ENS160::checkPartID () {
- uint16_t part_id;
-
- read16(ENS160_REG_PART_ID, &part_id);
- _delay_ms(ENS160_BOOTING);
-
- if (part_id == ENS160_PARTID) {
- _revENS16x = 0;
- return true;
-
- } else if (part_id == ENS161_PARTID) {
- _revENS16x = 1;
- return true;
- }
-
- return false;
-}
-
-// Initialize idle mode and confirms
-bool ScioSense_ENS160::clearCommand () {
- uint8_t status;
-
- if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_NOP)) {
- if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_CLRGPR)) {
- _delay_ms(ENS160_BOOTING);
- if (read8(ENS160_REG_DATA_STATUS, &status)) {
- return true;
- }
- }
- }
- _delay_ms(ENS160_BOOTING);
- return false;
-}
-
-// Read firmware revisions
-bool ScioSense_ENS160::getFirmware () {
- uint8_t i2cbuf[3];
-
- if (clearCommand()) {
- _delay_ms(ENS160_BOOTING);
- if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_GET_APPVER)) {
- if (readBytes(ENS160_REG_GPR_READ_4, i2cbuf, 3)) {
- _fw_ver_major = i2cbuf[0];
- _fw_ver_minor = i2cbuf[1];
- _fw_ver_build = i2cbuf[2];
- _revENS16x = this->_fw_ver_major > 6 ? 1 : 0;
- _delay_ms(ENS160_BOOTING);
- return true;
- }
- }
- }
- _delay_ms(ENS160_BOOTING);
- return false;
-}
-
-// Set operation mode of sensor
-bool ScioSense_ENS160::setMode (uint8_t mode) {
- //LP only valid for rev>0
- if ((mode == ENS160_OPMODE_LP) and (_revENS16x == 0)) {
- return false;
- }
- if (write8(ENS160_REG_OPMODE, mode)) {
- _delay_ms(ENS160_BOOTING);
- return true;
- }
- _delay_ms(ENS160_BOOTING);
- return false;
-}
-
-// Initialize definition of custom mode with <n> steps
-bool ScioSense_ENS160::initCustomMode (uint16_t stepNum) {
- if (stepNum > 0) {
- _stepCount = stepNum;
- if (setMode(ENS160_OPMODE_IDLE)) {
- if (clearCommand()) {
- if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_SETSEQ)) {
- _delay_ms(ENS160_BOOTING);
- return true;
- }
- }
- }
- }
- _delay_ms(ENS160_BOOTING);
- return false;
-}
-
-// Add a step to custom measurement profile with definition of duration, enabled data acquisition and temperature for each hotplate
-bool ScioSense_ENS160::addCustomStep (uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3) {
- uint8_t seq_ack;
- uint8_t temp;
-
- _delay_ms(ENS160_BOOTING);
-
- temp = (uint8_t)(((time / 24) - 1) << 6);
- if (measureHP0) {
- temp = temp | 0x20;
- }
- if (measureHP1) {
- temp = temp | 0x10;
- }
- if (measureHP2) {
- temp = temp | 0x08;
- }
- if (measureHP3) {
- temp = temp | 0x04;
- }
- if (!write8(ENS160_REG_GPR_WRITE_0, temp)) {
- return false;
- }
- temp = (uint8_t)(((time / 24) - 1) >> 2);
- if (!write8(ENS160_REG_GPR_WRITE_1, temp)) {
- return false;
- }
- if (!write8(ENS160_REG_GPR_WRITE_2, (uint8_t)(tempHP0 / 2))) {
- return false;
- }
- if (!write8(ENS160_REG_GPR_WRITE_3, (uint8_t)(tempHP1 / 2))) {
- return false;
- }
- if (write8(ENS160_REG_GPR_WRITE_4, (uint8_t)(tempHP2 / 2))) {
- return false;
- }
- if (write8(ENS160_REG_GPR_WRITE_5, (uint8_t)(tempHP3 / 2))) {
- return false;
- }
-
- if (write8(ENS160_REG_GPR_WRITE_6, (uint8_t)(_stepCount - 1))) {
- return false;
- }
-
- if (_stepCount == 1) {
- if (!write8(ENS160_REG_GPR_WRITE_7, 128)) {
- return false;
- }
- } else {
- if (!write8(ENS160_REG_GPR_WRITE_7, 0)) {
- return false;
- }
- }
- _delay_ms(ENS160_BOOTING);
-
- if (!read8(ENS160_REG_GPR_READ_7, &seq_ack)) {
- return false;
- }
- _delay_ms(ENS160_BOOTING);
-
- if ((ENS160_SEQ_ACK_COMPLETE | _stepCount) != seq_ack) {
- _stepCount++;
- return false;
- }
-
- return true;
-}
-
-bool ScioSense_ENS160::readStatus (uint8_t *status) {
- return read8(ENS160_REG_DATA_STATUS, status);
-}
-
-bool ScioSense_ENS160::readData (ENS160_DATA *data) {
- uint8_t buffer[1] = { 0x21 };
- return i2cDevice.write_then_read(buffer, 1, (uint8_t *)data, sizeof(ENS160_DATA));
-}
-
-// Perform prediction measurement and stores result in internal variables
-bool ScioSense_ENS160::measure (bool waitForNew) {
- uint8_t i2cbuf[8];
- uint8_t status;
-
- // Set default status for early bail out
- if (waitForNew) {
- do {
- if (!read8(ENS160_REG_DATA_STATUS, &status)) {
- return false;
- }
- _delay_ms(1);
- } while (!IS_NEWDAT(status));
- } else {
- if (!read8(ENS160_REG_DATA_STATUS, &status)) {
- return false;
- }
- }
-
-
- // Read predictions
- if (IS_NEWDAT(status)) {
- if (!readBytes(ENS160_REG_DATA_AQI, i2cbuf, 7)) {
- return false;
- }
- return false;
- _data_aqi = i2cbuf[0];
- _data_tvoc = i2cbuf[1] | ((uint16_t)i2cbuf[2] << 8);
- _data_eco2 = i2cbuf[3] | ((uint16_t)i2cbuf[4] << 8);
- if (_revENS16x > 0) {
- _data_aqi500 = ((uint16_t)i2cbuf[5]) | ((uint16_t)i2cbuf[6] << 8);
- } else {
- _data_aqi500 = 0;
- }
- return true;
- }
-
- return false;
-}
-
-// Perfrom raw measurement and stores result in internal variables
-bool ScioSense_ENS160::measureRaw (bool waitForNew) {
- uint8_t i2cbuf[8];
- uint8_t status;
-
- // Set default status for early bail out
- if (waitForNew) {
- do {
- _delay_ms(1);
- if (!read8(ENS160_REG_DATA_STATUS, &status)) {
- return false;
- }
- } while (!IS_NEWGPR(status));
- } else {
- if (!read8(ENS160_REG_DATA_STATUS, &status)) {
- return false;
- }
- }
-
- if (IS_NEWGPR(status)) {
-
- // Read raw resistance values
- if (!readBytes(ENS160_REG_GPR_READ_0, i2cbuf, 8)) {
- return false;
- }
- _hp0_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8)));
- _hp1_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[2] | ((uint16_t)i2cbuf[3] << 8)));
- _hp2_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[4] | ((uint16_t)i2cbuf[5] << 8)));
- _hp3_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[6] | ((uint16_t)i2cbuf[7] << 8)));
-
- // Read baselines
- if (!readBytes(ENS160_REG_DATA_BL, i2cbuf, 8)) {
- return false;
- }
- _hp0_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8)));
- _hp1_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[2] | ((uint16_t)i2cbuf[3] << 8)));
- _hp2_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[4] | ((uint16_t)i2cbuf[5] << 8)));
- _hp3_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[6] | ((uint16_t)i2cbuf[7] << 8)));
-
- if (!read8(ENS160_REG_DATA_MISR, i2cbuf)) {
- return false;
- }
- _misr = i2cbuf[0];
- return true;
- }
-
- return false;
-}
-
-
-// Writes t (degC) and h (%rh) to ENV_DATA. Returns false on I2C problems.
-bool ScioSense_ENS160::set_envdata (float t, float h) {
- uint16_t t_data = (uint16_t)((t + 273.15f) * 64.0f);
- uint16_t rh_data = (uint16_t)(h * 512.0f);
- return this->set_envdata210(t_data, rh_data);
-}
-
-// Writes t and h (in ENS210 format) to ENV_DATA. Returns false on I2C problems.
-bool ScioSense_ENS160::set_envdata210 (uint16_t t, uint16_t h) {
- //uint16_t temp;
- uint8_t trh_in[4];
-
- //temp = (uint16_t)((t + 273.15f) * 64.0f);
- trh_in[0] = t & 0xff;
- trh_in[1] = (t >> 8) & 0xff;
-
- //temp = (uint16_t)(h * 512.0f);
- trh_in[2] = h & 0xff;
- trh_in[3] = (h >> 8) & 0xff;
-
- if (!i2cDevice.writeByteAndBuffer(ENS160_REG_TEMP_IN, trh_in, 4)) {
- return false;
- }
-
- return true;
-}
+++ /dev/null
-/*
- ScioSense_ENS160.h - Library for the ENS160 sensor with I2C interface from ScioSense
- 2023 Mar 23 v6 Christoph Friese Bugfix measurement routine, prepare next release
- 2021 July 29 v4 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams
- 2020 Apr 06 v3 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams
- 2020 Feb 15 v2 Giuseppe Pasetti Corrected firmware flash option
- 2019 May 05 v1 Christoph Friese Created
- based on application note "ENS160 Software Integration.pdf" rev 0.01
-*/
-
-#ifndef __SCIOSENSE_ENS160_H_
-#define __SCIOSENSE_ENS160_H_
-
-#include "../i2cmaster.hpp"
-#include <stdint.h>
-#define byte uint8_t
-
-// #if (ARDUINO >= 100)
-// #include "Arduino.h"
-// #else
-// #include "WProgram.h"
-// #endif
-
-// #include <Wire.h>
-
-// Chip constants
-#define ENS160_PARTID 0x0160
-#define ENS161_PARTID 0x0161
-#define ENS160_BOOTING 10
-
-// 7-bit I2C slave address of the ENS160
-#define ENS160_I2CADDR_0 0x52 //ADDR low
-#define ENS160_I2CADDR_1 0x53 //ADDR high
-
-// ENS160 registers for version V0
-#define ENS160_REG_PART_ID 0x00 // 2 byte register
-#define ENS160_REG_OPMODE 0x10
-#define ENS160_REG_CONFIG 0x11
-#define ENS160_REG_COMMAND 0x12
-#define ENS160_REG_TEMP_IN 0x13
-#define ENS160_REG_RH_IN 0x15
-#define ENS160_REG_DATA_STATUS 0x20
-#define ENS160_REG_DATA_AQI 0x21
-#define ENS160_REG_DATA_TVOC 0x22
-#define ENS160_REG_DATA_ECO2 0x24
-#define ENS160_REG_DATA_BL 0x28
-#define ENS160_REG_DATA_T 0x30
-#define ENS160_REG_DATA_RH 0x32
-#define ENS160_REG_DATA_MISR 0x38
-#define ENS160_REG_GPR_WRITE_0 0x40
-#define ENS160_REG_GPR_WRITE_1 ENS160_REG_GPR_WRITE_0 + 1
-#define ENS160_REG_GPR_WRITE_2 ENS160_REG_GPR_WRITE_0 + 2
-#define ENS160_REG_GPR_WRITE_3 ENS160_REG_GPR_WRITE_0 + 3
-#define ENS160_REG_GPR_WRITE_4 ENS160_REG_GPR_WRITE_0 + 4
-#define ENS160_REG_GPR_WRITE_5 ENS160_REG_GPR_WRITE_0 + 5
-#define ENS160_REG_GPR_WRITE_6 ENS160_REG_GPR_WRITE_0 + 6
-#define ENS160_REG_GPR_WRITE_7 ENS160_REG_GPR_WRITE_0 + 7
-#define ENS160_REG_GPR_READ_0 0x48
-#define ENS160_REG_GPR_READ_4 ENS160_REG_GPR_READ_0 + 4
-#define ENS160_REG_GPR_READ_6 ENS160_REG_GPR_READ_0 + 6
-#define ENS160_REG_GPR_READ_7 ENS160_REG_GPR_READ_0 + 7
-
-//ENS160 data register fields
-#define ENS160_COMMAND_NOP 0x00
-#define ENS160_COMMAND_CLRGPR 0xCC
-#define ENS160_COMMAND_GET_APPVER 0x0E
-#define ENS160_COMMAND_SETTH 0x02
-#define ENS160_COMMAND_SETSEQ 0xC2
-
-#define ENS160_OPMODE_RESET 0xF0
-#define ENS160_OPMODE_DEP_SLEEP 0x00
-#define ENS160_OPMODE_IDLE 0x01
-#define ENS160_OPMODE_STD 0x02
-#define ENS160_OPMODE_LP 0x03
-#define ENS160_OPMODE_CUSTOM 0xC0
-
-#define ENS160_BL_CMD_START 0x02
-#define ENS160_BL_CMD_ERASE_APP 0x04
-#define ENS160_BL_CMD_ERASE_BLINE 0x06
-#define ENS160_BL_CMD_WRITE 0x08
-#define ENS160_BL_CMD_VERIFY 0x0A
-#define ENS160_BL_CMD_GET_BLVER 0x0C
-#define ENS160_BL_CMD_GET_APPVER 0x0E
-#define ENS160_BL_CMD_EXITBL 0x12
-
-#define ENS160_SEQ_ACK_NOTCOMPLETE 0x80
-#define ENS160_SEQ_ACK_COMPLETE 0xC0
-
-#define IS_ENS160_SEQ_ACK_NOT_COMPLETE(x) (ENS160_SEQ_ACK_NOTCOMPLETE == (ENS160_SEQ_ACK_NOTCOMPLETE & (x)))
-#define IS_ENS160_SEQ_ACK_COMPLETE(x) (ENS160_SEQ_ACK_COMPLETE == (ENS160_SEQ_ACK_COMPLETE & (x)))
-
-#define ENS160_DATA_STATUS_NEWDAT 0x02
-#define ENS160_DATA_STATUS_NEWGPR 0x01
-
-#define IS_NEWDAT(x) (ENS160_DATA_STATUS_NEWDAT == (ENS160_DATA_STATUS_NEWDAT & (x)))
-#define IS_NEWGPR(x) (ENS160_DATA_STATUS_NEWGPR == (ENS160_DATA_STATUS_NEWGPR & (x)))
-#define IS_NEW_DATA_AVAILABLE(x) (0 != ((ENS160_DATA_STATUS_NEWDAT | ENS160_DATA_STATUS_NEWGPR ) & (x)))
-
-#define CONVERT_RS_RAW2OHMS_I(x) (1 << ((x) >> 11))
-#define CONVERT_RS_RAW2OHMS_F(x) (pow (2, (float)(x) / 2048))
-
-typedef struct {
- uint8_t aqi;
- uint16_t tvoc;
- uint16_t eco2;
-} ENS160_DATA;
-
-class ScioSense_ENS160 {
-
- public:
- ScioSense_ENS160();
-
- void setI2C(uint8_t sda, uint8_t scl); // Function to redefine I2C pins
-
- bool begin(); // Init I2C communication, resets ENS160 and checks its PART_ID. Returns false on I2C problems or wrong PART_ID.
- uint8_t revENS16x() { return this->_revENS16x; } // Report version of sensor (0: ENS160, 1: ENS161)
- bool setMode(uint8_t mode); // Set operation mode of sensor
-
- bool initCustomMode(uint16_t stepNum); // Initialize definition of custom mode with <n> steps
- bool addCustomStep(uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3);
- // Add a step to custom measurement profile with definition of duration, enabled data acquisition and temperature for each hotplate
-
- bool readData (ENS160_DATA *data);
- bool readStatus(uint8_t *status);
- bool measure(bool waitForNew); // Perform measurement and stores result in internal variables
- bool measureRaw(bool waitForNew); // Perform raw measurement and stores result in internal variables
- bool set_envdata(float t, float h); // Writes t (degC) and h (%rh) to ENV_DATA. Returns "0" if I2C transmission is successful
- bool set_envdata210(uint16_t t, uint16_t h); // Writes t and h (in ENS210 format) to ENV_DATA. Returns "0" if I2C transmission is successful
- uint8_t getMajorRev() { return this->_fw_ver_major; } // Get major revision number of used firmware
- uint8_t getMinorRev() { return this->_fw_ver_minor; } // Get minor revision number of used firmware
- uint8_t getBuild() { return this->_fw_ver_build; } // Get build revision number of used firmware
-
- uint8_t getAQI() { return this->_data_aqi; } // Get AQI value of last measurement
- uint16_t getTVOC() { return this->_data_tvoc; } // Get TVOC value of last measurement
- uint16_t geteCO2() { return this->_data_eco2; } // Get eCO2 value of last measurement
- uint16_t getAQI500() { return this->_data_aqi500; } // Get AQI500 value of last measurement
- uint32_t getHP0() { return this->_hp0_rs; } // Get resistance of HP0 of last measurement
- uint32_t getHP1() { return this->_hp1_rs; } // Get resistance of HP1 of last measurement
- uint32_t getHP2() { return this->_hp2_rs; } // Get resistance of HP2 of last measurement
- uint32_t getHP3() { return this->_hp3_rs; } // Get resistance of HP3 of last measurement
- uint32_t getHP0BL() { return this->_hp0_bl; } // Get baseline resistance of HP0 of last measurement
- uint32_t getHP1BL() { return this->_hp1_bl; } // Get baseline resistance of HP1 of last measurement
- uint32_t getHP2BL() { return this->_hp2_bl; } // Get baseline resistance of HP2 of last measurement
- uint32_t getHP3BL() { return this->_hp3_bl; } // Get baseline resistance of HP3 of last measurement
- uint8_t getMISR() { return this->_misr; } // Return status code of sensor
-
- private:
- I2cMaster i2cDevice;
- bool reset(); // Sends a reset to the ENS160. Returns false on I2C problems.
- bool checkPartID(); // Reads the part ID and confirms valid sensor
- bool clearCommand(); // Initialize idle mode and confirms
- bool getFirmware(); // Read firmware revisions
-
- uint8_t _revENS16x; // ENS160 or ENS161 connected? (FW >7)
-
- uint8_t _fw_ver_major;
- uint8_t _fw_ver_minor;
- uint8_t _fw_ver_build;
-
- uint16_t _stepCount; // Counter for custom sequence
-
- uint8_t _data_aqi;
- uint16_t _data_tvoc;
- uint16_t _data_eco2;
- uint16_t _data_aqi500;
- uint32_t _hp0_rs;
- uint32_t _hp0_bl;
- uint32_t _hp1_rs;
- uint32_t _hp1_bl;
- uint32_t _hp2_rs;
- uint32_t _hp2_bl;
- uint32_t _hp3_rs;
- uint32_t _hp3_bl;
- uint16_t _temp;
- int _slaveaddr; // Slave address of the ENS160
- uint8_t _misr;
-
- uint8_t _seq_steps[1][8];
-
- bool write8(byte reg, byte value);
- bool read8 (byte reg, byte *value);
- bool read16 (byte reg, uint16_t *value);
- bool read16LE (byte reg, uint16_t *value);
- bool readBytes (byte reg, uint8_t *bytes, uint8_t len);
-};
-
-
-#endif
+++ /dev/null
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software< /span>
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and
- * extended sensor support to include color, voltage and current */
-
-#ifndef _ADAFRUIT_SENSOR_H
-#define _ADAFRUIT_SENSOR_H
-
-#ifndef ARDUINO
-#include <stdint.h>
-#elif ARDUINO >= 100
-#include "Arduino.h"
-#include "Print.h"
-#else
-#include "WProgram.h"
-#endif
-
-/* Constants */
-#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */
-#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */
-#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */
-#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH)
-#define SENSORS_MAGFIELD_EARTH_MAX \
- (60.0F) /**< Maximum magnetic field on Earth's surface */
-#define SENSORS_MAGFIELD_EARTH_MIN \
- (30.0F) /**< Minimum magnetic field on Earth's surface */
-#define SENSORS_PRESSURE_SEALEVELHPA \
- (1013.25F) /**< Average sea level pressure is 1013.25 hPa */
-#define SENSORS_DPS_TO_RADS \
- (0.017453293F) /**< Degrees/s to rad/s multiplier \
- */
-#define SENSORS_RADS_TO_DPS \
- (57.29577793F) /**< Rad/s to degrees/s multiplier */
-#define SENSORS_GAUSS_TO_MICROTESLA \
- (100) /**< Gauss to micro-Tesla multiplier */
-
-/** Sensor types */
-typedef enum {
- SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */
- SENSOR_TYPE_MAGNETIC_FIELD = (2),
- SENSOR_TYPE_ORIENTATION = (3),
- SENSOR_TYPE_GYROSCOPE = (4),
- SENSOR_TYPE_LIGHT = (5),
- SENSOR_TYPE_PRESSURE = (6),
- SENSOR_TYPE_PROXIMITY = (8),
- SENSOR_TYPE_GRAVITY = (9),
- SENSOR_TYPE_LINEAR_ACCELERATION =
- (10), /**< Acceleration not including gravity */
- SENSOR_TYPE_ROTATION_VECTOR = (11),
- SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
- SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
- SENSOR_TYPE_OBJECT_TEMPERATURE = (14),
- SENSOR_TYPE_VOLTAGE = (15),
- SENSOR_TYPE_CURRENT = (16),
- SENSOR_TYPE_COLOR = (17),
- SENSOR_TYPE_TVOC = (18),
- SENSOR_TYPE_VOC_INDEX = (19),
- SENSOR_TYPE_NOX_INDEX = (20),
- SENSOR_TYPE_CO2 = (21),
- SENSOR_TYPE_ECO2 = (22),
- SENSOR_TYPE_PM10_STD = (23),
- SENSOR_TYPE_PM25_STD = (24),
- SENSOR_TYPE_PM100_STD = (25),
- SENSOR_TYPE_PM10_ENV = (26),
- SENSOR_TYPE_PM25_ENV = (27),
- SENSOR_TYPE_PM100_ENV = (28),
- SENSOR_TYPE_GAS_RESISTANCE = (29),
- SENSOR_TYPE_UNITLESS_PERCENT = (30),
- SENSOR_TYPE_ALTITUDE = (31)
-} sensors_type_t;
-
-/** struct sensors_vec_s is used to return a vector in a common format. */
-typedef struct {
- union {
- float v[3]; ///< 3D vector elements
- struct {
- float x; ///< X component of vector
- float y; ///< Y component of vector
- float z; ///< Z component of vector
- }; ///< Struct for holding XYZ component
- /* Orientation sensors */
- struct {
- float roll; /**< Rotation around the longitudinal axis (the plane body, 'X
- axis'). Roll is positive and increasing when moving
- downward. -90 degrees <= roll <= 90 degrees */
- float pitch; /**< Rotation around the lateral axis (the wing span, 'Y
- axis'). Pitch is positive and increasing when moving
- upwards. -180 degrees <= pitch <= 180 degrees) */
- float heading; /**< Angle between the longitudinal axis (the plane body)
- and magnetic north, measured clockwise when viewing from
- the top of the device. 0-359 degrees */
- }; ///< Struct for holding roll/pitch/heading
- }; ///< Union that can hold 3D vector array, XYZ components or
- ///< roll/pitch/heading
- int8_t status; ///< Status byte
- uint8_t reserved[3]; ///< Reserved
-} sensors_vec_t;
-
-/** struct sensors_color_s is used to return color data in a common format. */
-typedef struct {
- union {
- float c[3]; ///< Raw 3-element data
- /* RGB color space */
- struct {
- float r; /**< Red component */
- float g; /**< Green component */
- float b; /**< Blue component */
- }; ///< RGB data in floating point notation
- }; ///< Union of various ways to describe RGB colorspace
- uint32_t rgba; /**< 24-bit RGBA value */
-} sensors_color_t;
-
-/* Sensor event (36 bytes) */
-/** struct sensor_event_s is used to provide a single sensor event in a common
- * format. */
-typedef struct {
- int32_t version; /**< must be sizeof(struct sensors_event_t) */
- int32_t sensor_id; /**< unique sensor identifier */
- int32_t type; /**< sensor type */
- int32_t reserved0; /**< reserved */
- int32_t timestamp; /**< time is in milliseconds */
- union {
- float data[4]; ///< Raw data */
- sensors_vec_t acceleration; /**< acceleration values are in meter per second
- per second (m/s^2) */
- sensors_vec_t
- magnetic; /**< magnetic vector values are in micro-Tesla (uT) */
- sensors_vec_t orientation; /**< orientation values are in degrees */
- sensors_vec_t gyro; /**< gyroscope values are in rad/s */
- float temperature; /**< temperature is in degrees centigrade (Celsius) */
- float distance; /**< distance in centimeters */
- float light; /**< light in SI lux units */
- float pressure; /**< pressure in hectopascal (hPa) */
- float relative_humidity; /**< relative humidity in percent */
- float current; /**< current in milliamps (mA) */
- float voltage; /**< voltage in volts (V) */
- float tvoc; /**< Total Volatile Organic Compounds, in ppb */
- float voc_index; /**< VOC (Volatile Organic Compound) index where 100 is
- normal (unitless) */
- float nox_index; /**< NOx (Nitrogen Oxides) index where 100 is normal
- (unitless) */
- float CO2; /**< Measured CO2 in parts per million (ppm) */
- float eCO2; /**< equivalent/estimated CO2 in parts per million (ppm
- estimated from some other measurement) */
- float pm10_std; /**< Standard Particulate Matter <=1.0 in parts per million
- (ppm) */
- float pm25_std; /**< Standard Particulate Matter <=2.5 in parts per million
- (ppm) */
- float pm100_std; /**< Standard Particulate Matter <=10.0 in parts per
- million (ppm) */
- float pm10_env; /**< Environmental Particulate Matter <=1.0 in parts per
- million (ppm) */
- float pm25_env; /**< Environmental Particulate Matter <=2.5 in parts per
- million (ppm) */
- float pm100_env; /**< Environmental Particulate Matter <=10.0 in parts per
- million (ppm) */
- float gas_resistance; /**< Proportional to the amount of VOC particles in
- the air (Ohms) */
- float unitless_percent; /**<Percentage, unit-less (%) */
- sensors_color_t color; /**< color in RGB component values */
- float altitude; /**< Distance between a reference datum and a point or
- object, in meters. */
- }; ///< Union for the wide ranges of data we can carry
-} sensors_event_t;
-
-/* Sensor details (40 bytes) */
-/** struct sensor_s is used to describe basic information about a specific
- * sensor. */
-typedef struct {
- char name[12]; /**< sensor name */
- int32_t version; /**< version of the hardware + driver */
- int32_t sensor_id; /**< unique sensor identifier */
- int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */
- float max_value; /**< maximum value of this sensor's value in SI units */
- float min_value; /**< minimum value of this sensor's value in SI units */
- float resolution; /**< smallest difference between two values reported by this
- sensor */
- int32_t min_delay; /**< min delay in microseconds between events. zero = not a
- constant rate */
-} sensor_t;
-
-/** @brief Common sensor interface to unify various sensors.
- * Intentionally modeled after sensors.h in the Android API:
- * https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h
- */
-class Adafruit_Sensor {
-public:
- // Constructor(s)
- Adafruit_Sensor() {}
-// virtual ~Adafruit_Sensor() {}
-
-// // These must be defined by the subclass
-
-// /*! @brief Whether we should automatically change the range (if possible) for
-// higher precision
-// @param enabled True if we will try to autorange */
-// virtual void enableAutoRange(bool enabled) {
-// (void)enabled; /* suppress unused warning */
-// };
-
-// /*! @brief Get the latest sensor event
-// @returns True if able to fetch an event */
-// virtual bool getEvent(sensors_event_t *) = 0;
-// /*! @brief Get info about the sensor itself */
-// virtual void getSensor(sensor_t *) = 0;
-
-// void printSensorDetails(void);
-};
-
-#endif
+++ /dev/null
-#include <avr/io.h>
-#include <stdio.h>
-
-#include "i2cmaster.hpp"
-
-I2cMaster::I2cMaster () {
- address = 0;
- timer = 0;
-}
-
-void I2cMaster::tick1ms () {
- if (timer > 0) {
- timer--;
- }
-}
-
-bool I2cMaster::begin (uint8_t addr) {
- this->address = addr;
- // TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4);
- TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
- TWCR = (1 << TWEN);
- return true;
-}
-
-void I2cMaster::end () {
- TWCR = (1 << TWEN);
- TWBR = 0;
-}
-
-bool I2cMaster::read (uint8_t *buffer, uint8_t len) {
- if (start(true)) {
- if (readBytes(buffer, len)) {
- if (stop()) {
- return true;
- }
- }
- }
- return false;
-}
-
-
-bool I2cMaster::write (const uint8_t *buffer, uint8_t len) {
- if (start(false)) {
- if (writeBytes(buffer, len)) {
- if (stop()) {
- return true;
- }
- }
- }
- return false;
-}
-
-bool I2cMaster::writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len) {
- if (start(false)) {
- do {
- TWDR = byte;
- TWCR = (1 << TWINT) | (1 << TWEN); // send byte
- while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
- if ((TWSR & 0xf8) != 0x28) {
- return false;
- }
- byte = *buffer++;
- } while (len-- > 0);
- return true;
- }
- return false;
-}
-
-
-bool I2cMaster::write_then_read (const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len) {
- if (start(false)) {
- if (writeBytes(write_buffer, write_len)) {
- if (start(true)) {
- if (readBytes(read_buffer, read_len)) {
- if (stop()) {
- return true;
- }
- }
- }
- }
- }
- return false;
-}
-
-// -------------------------------------------------------------
-
-bool I2cMaster::readBytes (uint8_t *buffer, uint8_t len) {
- while (len-- > 0) {
- if (len > 0) {
- TWCR = (1 << TWEA) | (1 << TWINT) | (1 << TWEN); // read data byte with ACK enabled
- } else {
- TWCR = (1 << TWINT) | (1 << TWEN); // read data byte with ACK disabled
- }
- while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
- uint8_t sr = TWSR & 0xf8;
- if ((len > 0 && sr != 0x50) || (len == 0 && sr != 0x58)) {
- return false;
- }
- *buffer++ = TWDR;
- }
- return true;
-}
-
-bool I2cMaster::writeBytes (const uint8_t *buffer, uint8_t len) {
- while (len-- > 0) {
- // printf_P(PSTR("[wB:len=%d, byte=%02x]"), len + 1, *buffer);
- TWDR = *buffer++;
- TWCR = (1 << TWINT) | (1 << TWEN); // send data byte
- timer = 5;
- while (timer > 0 && !(TWCR & (1 << TWINT))) {}; // wait until last action done
- if (!timer || (TWSR & 0xf8) != 0x28) {
- return false;
- }
- }
- return true;
-}
-
-
-bool I2cMaster::start (bool read) {
- TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send START condition
- timer = 5;
- while (timer > 0 && !(TWCR & (1 << TWINT))) {}; // wait until last action done
- uint8_t sr = TWSR & 0xf8;
- if (!timer || (sr != 0x08 && sr != 0x10)) {
- return false;
- }
- TWDR = (address << 1) | (read ? 1 : 0); // address + R/nW
- TWCR = (1 << TWINT) | (1 << TWEN); // send address/RW
- timer = 5;
- while (timer > 0 && !(TWCR & (1 << TWINT))) {}; // wait until last action done
- sr = TWSR & 0xf8;
- if (!timer || (!read && sr != 0x18) || (read && sr != 0x40)) {
- return false;
- }
- return true;
-}
-
-bool I2cMaster::stop () {
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
- while (TWCR & ( 1 << TWSTO));
- return true;
-}
-
+++ /dev/null
-#ifndef I2C_MASTER
-#define I2C_MASTER
-
-#include <stdint.h>
-
-class I2cMaster {
- public:
- static void end ();
-
- public:
- I2cMaster ();
- void tick1ms ();
- bool begin (uint8_t addr);
- bool read (uint8_t *buffer, uint8_t len);
- bool write(const uint8_t *buffer, uint8_t len);
- bool write_then_read(const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len);
- bool writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len);
-
- private:
- uint8_t address;
- uint8_t timer;
- bool start (bool read);
- bool stop ();
- bool writeBytes (const uint8_t *buffer, uint8_t len);
- bool readBytes (uint8_t *buffer, uint8_t len);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <avr/io.h>
-#include <stdio.h>
-#include <util/atomic.h>
-
-#include "i2cslave.hpp"
-
-I2cSlave::I2cSlave () {
- timer = 0;
- fromMaster.rIndex = 0;
- fromMaster.wIndex = 0;
- toMaster.rIndex = 0;
- toMaster.wIndex = 0;
-}
-
-void I2cSlave::tick1ms () {
- if (timer > 0) {
- timer--;
- }
-}
-
-bool I2cSlave::begin (uint8_t addr, bool acceptGeneralCalls) {
- if (addr > 127) {
- return false;
- }
- TWAR = addr << 1 | (acceptGeneralCalls ? 1 : 0);
- TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
- TWCR = (1 << TWEA) | (1 << TWEN) | (1 << TWIE);
- return true;
-}
-
-void I2cSlave::end () {
- TWCR = (1 << TWEN);
- TWBR = 0;
-}
-
-int I2cSlave::read () {
- return getByte(fromMaster);
-}
-
-void I2cSlave::write (uint8_t byte) {
- putByte(toMaster, byte);
-}
-
-
-void I2cSlave::putByte (RingBuffer& buffer, uint8_t byte) {
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- buffer.data[buffer.wIndex++] = byte;
- if (buffer.wIndex >= sizeof(buffer.data)) {
- buffer.wIndex = 0;
- }
- if (buffer.wIndex == buffer.rIndex) {
- buffer.rIndex++;
- if (buffer.rIndex >= sizeof(buffer.data)) {
- buffer.rIndex = 0;
- }
- }
- }
-}
-
-int I2cSlave::getByte (RingBuffer& buffer) {
- uint8_t b;
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- if (buffer.rIndex == buffer.wIndex) {
- return EOF;
- }
- b = buffer.data[buffer.rIndex++];
- if (buffer.rIndex >= sizeof(buffer.data)) {
- buffer.rIndex = 0;
- }
- }
- return b;
-}
-
-void I2cSlave::handleTWIIsr () {
- uint8_t sr = TWSR & 0xf8;
- switch (sr) {
- case 0x80: { // Previously addressed with own SLA+W; data has been received; ACK has been returned
- putByte(fromMaster, TWDR);
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); // no TWEA -> only one byte accepted
- break;
- }
- case 0xa8: { // Own SLA+R has been received; ACK has been returned
- int response = getByte(toMaster);;
- TWDR = response < 0 ? 0x00 : (uint8_t)response;
- TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWIE); // no TWEA -> only one byte accepted
- break;
- }
- default: TWCR = (1 << TWINT) | (1 << TWEA) | (1 << TWEN) | (1 << TWIE); break;
- }
-
-}
-
+++ /dev/null
-#ifndef I2C_SLAVE
-#define I2C_SLAVE
-
-#include <stdint.h>
-
-class I2cSlave {
- private:
- typedef struct {
- uint8_t rIndex;
- uint8_t wIndex;
- uint8_t data[8];
- } RingBuffer;
-
- public:
- I2cSlave ();
- void tick1ms ();
- bool begin (uint8_t addr, bool acceptGeneralCalls);
- void end ();
- void handleTWIIsr ();
- int read ();
- void write (uint8_t byte);
-
- private:
- uint8_t timer;
- RingBuffer fromMaster;
- RingBuffer toMaster;
- void putByte (RingBuffer& buffer, uint8_t byte);
- int getByte (RingBuffer& buffer);
-
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <avr/io.h>
-#include <avr/pgmspace.h>
-#include <avr/interrupt.h>
-#include <util/delay.h>
-
-#include <stdio.h>
-#include <util/atomic.h>
-
-#include "main.hpp"
-#include "units/encoder.hpp"
-#include "units/i2c.hpp"
-#include "units/led.hpp"
-#include "units/ieee485.hpp"
-#include "units/led.hpp"
-#include "units/lcd.hpp"
-#include "units/switch.hpp"
-#include "units/rgb.hpp"
-#include "units/seg7.hpp"
-#include "units/poti.hpp"
-#include "units/r2r.hpp"
-#include "units/motor.hpp"
-#include "units/portexp.hpp"
-#include "units/uart1.hpp"
-#include "units/modbus.hpp"
-
-extern "C" {
- void __cxa_pure_virtual () {
- }
-
- int __cxa_guard_acquire(uint8_t *g) {
- return 0;
- }
-
- void __cxa_guard_release(uint8_t *g) {}
-
- void __cxa_guard_abort(uint8_t *g) {}
-
-
- int uart_putchar(char c, FILE *stream) {
- if (c == '\n') {
- uart_putchar('\r', stream);
- }
- if (stream == stdout) {
- loop_until_bit_is_set(UCSR0A, UDRE0);
- UDR0 = c;
- }
- return 0;
- }
-
-
- uint64_t volatile systemMillis = 0;
- uint8_t volatile uartBuffer[32];
- uint8_t volatile rIndex = 0;
- uint8_t volatile wIndex = 0;
-
- int uart_getchar (FILE *stream) {
- // if (rIndex == wIndex) {
- // // nothing in buffer
- // return EOF;
- // }
- // printf_P(PSTR(" r%d"), rIndex);
- while (rIndex == wIndex) {
- // wait for character
- }
-
- // don't use "char c" because german special characters would lead to negative return -> stream error
- // char c = uartBuffer[rIndex++];
-
- uint8_t c = uartBuffer[rIndex++];
- // printf_P(PSTR("(%02x) "), c);
- if (c == '\r') {
- c = '\n';
- }
- putchar(c); // echo on terminal
- return c;
- }
-
- static FILE mystdout = { 0, 0, _FDEV_SETUP_WRITE , 0, 0, uart_putchar, NULL, 0 };
- static FILE mystdin = { 0, 0, _FDEV_SETUP_READ , 0, 0, NULL, uart_getchar, 0 };
-
- static volatile uint32_t timer1ms = 0;
- static volatile int keyUart0 = EOF;
-
- Led led;
- Switch sw;
- Rgb rgb;
- Seg7 seg7;
- Poti poti;
- Encoder encoder;
- R2r r2r;
- Motor motor;
- PortExp portExp;
- Lcd lcd;
- Uart1 uart1;
- Modbus modbus;
- Ieee485 ieee485;
- I2c i2cSparkfun(I2c::SparkFunEnvCombo);
- I2c i2cMaster(I2c::Master);
- I2c i2cSlave(I2c::Slave);
-
-}
-
-void setTimer (uint32_t ms) {
- ATOMIC_BLOCK(ATOMIC_FORCEON) {
- timer1ms = ms;
- }
-}
-
-int wait (uint32_t ms) {
- setTimer(ms);
- do {
- ATOMIC_BLOCK(ATOMIC_FORCEON) {
- ms = timer1ms;
- }
- } while (ms > 0 && keyUart0 == EOF);
- return keyUart0;
-}
-
-int main () {
-
- #ifdef __AVR_ATmega644P__
- // Nano-644 LEDs (Green, Orange, Red)
- DDRC |= (1 << DDC4) | (1 << DDC3) | (1 << DDC2);
- PORTC &= ~((1 << PORT4) | (1 << PORT3) | (1 << PORT2));
-
- // Nano-644 push button SW2
- DDRC &= ~(1 << DDC5);
- PORTC |= (1 << PORT5); // enable internal pullup resistor
- #endif
-
- #ifdef __AVR_ATmega328P__
- DDRB |= (1 << PB5);
- PORTB &= ~(1 << PB5);
- #endif
-
- // UART0 interface on Nano-644
- UCSR0A = (1 << U2X0);
- UCSR0B = (1 << RXCIE0) | (1 << RXEN0) | (1 <<TXEN0);
- UCSR0C = (1 << UCSZ01) | ( 1<< UCSZ00);
- UBRR0H = 0;
- UBRR0L = F_CPU / 8 / 115200 - 1;
-
- TCCR2A = (1 << WGM21);
- TCCR2B = (1 << CS21); // CTC, F_CPU/8=1.5MHz
- OCR2A = 150; // 150/1.5E6 = 0.1ms
- TIMSK2 = (1 << OCIE2A);
-
- stdout = &mystdout;
- stdin = &mystdin;
-
- sei();
-
- #ifdef __AVR_ATmega644P__
- TestUnit *unit[] = {
- &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &portExp, &lcd, &uart1, &modbus, &ieee485,
- &i2cMaster, &i2cSlave, &i2cSparkfun
- };
- #endif
-
- #ifdef __AVR_ATmega328P__
- TestUnit *unit[] = {
- &led, &sw, &rgb, &seg7, &poti, &encoder, &r2r, &motor, &lcd,
- &i2cMaster, &i2cSlave, &i2cSparkfun
- };
- #endif
-
- while (1) {
- uint16_t i;
- char s[4];
- do {
- printf_P(PSTR("\n\n=============================\n\n"));
- printf_P(PSTR("Available units:\n\n"));
- for (i = 0; i < sizeof(unit) / sizeof(unit[0]); i++) {
- TestUnit *pu = unit[i];
- printf_P(PSTR("%3x ... "), i);
- printf_P(pu->getName());
- printf_P(PSTR("\n"));
- }
- printf_P(PSTR("\nSelect unit: "));
- rIndex = 0; wIndex = 0;
- fgets(s, sizeof(s), stdin);
- } while (sscanf(s, "%x", &i) != 1 || i < 0 || i >= sizeof(unit) / sizeof(unit[0]) );
-
- TestUnit *pu = unit[i];
- printf_P(PSTR("\n\n[")); printf_P(pu->getName()); printf_P(PSTR("]: "));
- keyUart0 = EOF;
-
- pu->init();
- for (uint8_t subtest = 0; subtest < 0xff; subtest++) {
- printf_P(PSTR("\n%4d: "), subtest);
- if (pu->run(subtest) < 0) {
- break;
- }
- if (keyUart0 == 27) {
- keyUart0 = EOF;
- break;
- }
- keyUart0 = EOF;
- }
- pu->cleanup();
- }
-}
-
-uint64_t millis () {
- volatile uint64_t millis = systemMillis;
- ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
- millis = systemMillis;
- }
- return millis;
-}
-
-#ifndef USART0_RX_vect
- #define USART0_RX_vect USART_RX_vect
-#endif
-ISR (USART0_RX_vect) {
- uint8_t b = UDR0;
- keyUart0 = b;
- uartBuffer[wIndex++] = b;
- // printf_P(PSTR(" w%d(%02x)"), wIndex, b);
- if (wIndex == rIndex) {
- // buffer overflow, kick out oldest byte
- rIndex++;
- }
-}
-
-#ifdef USART1_RX_vect
- ISR (USART1_RX_vect) {
- uint8_t b = UDR1;
- if (modbus.enabled) {
- modbus.handleRxByte(b);
- }
- if (uart1.enabled) {
- uart1.handleRxByte(b);
- }
- if (ieee485.enabled) {
- ieee485.handleRxByte(b);
- }
- }
-#endif
-
-ISR (TWI_vect) {
- if (i2cMaster.enabled) {
- i2cMaster.handleTwiIrq();
- } else if (i2cSlave.enabled) {
- i2cSlave.handleTwiIrq();
- } else if (i2cSparkfun.enabled) {
- i2cSparkfun.handleTwiIrq();
- } else {
- TWCR = (1 << TWINT); // clear interrupt request bit and disable TWI
- }
-}
-
-ISR (TIMER2_COMPA_vect) { // every 100us
- static uint16_t timer500ms = 0;
- static uint8_t timer100us = 0;
-
- if (encoder.enabled) {
- encoder.tick100us();
- }
- if (motor.enabled) {
- motor.tick100us();
- }
-
- timer100us++;
- if (timer100us >= 10) {
- timer100us = 0;
- if (timer1ms > 0) {
- timer1ms--;
- }
- systemMillis++;
- i2cMaster.tick1ms();
- i2cSlave.tick1ms();
- i2cSparkfun.tick1ms();
- }
-
- timer500ms++;
- if (timer500ms >= 5000) {
- #ifdef __AVR_ATmega644P__
- PORTC ^= (1 << PC3); // orange LED blinking
- #endif
- #ifdef __AVR_ATmega328P__
- if (!seg7.enabled) {
- PORTB ^= (1 << PB5); // LED L
- }
- #endif
- timer500ms = 0;
- }
-}
-
+++ /dev/null
-#ifndef MAIN_HPP
-#define MAIN_HPP
-
-#include <stdint.h>
-#include <avr/pgmspace.h>
-
-#define ENTER '\r'
-#define CTRLC '\003'
-
-extern int wait (uint32_t ms);
-extern uint64_t millis ();
-
-class TestUnit {
- public:
- virtual int8_t run (uint8_t subtest) = 0;
- virtual void init () = 0;
- virtual void cleanup () = 0;
- virtual PGM_P getName () = 0;
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-
-#include "encoder.hpp"
-#include "../main.hpp"
-
-// Encoder signals on rotation clockwise 1 step:
-// A -----____------ one char app. 1ms..2ms (rotation speed)
-// B -------___-----
-// one step when: A = 0, B= 1->0
-
-// Encoder signals on rotation counterclockwise 1 step:
-// A -----____------ one char app. 1ms..2ms (rotation speed)
-// B --______-----
-// one step when: A = 0, B= 0->1
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // ---------------------------------------------------------------
- // PB0/T0 ... Encoder A
- // PB1/T1 ... Encoder B
- // PB2/INT2 ... push switch of encoder (pushed = 0)
-
- void Encoder::init () {
- DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0));
- PORTB |= (1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0); // enable pullup
- enabled = 1;
- }
-
- void Encoder::cleanup () {
- enabled = 0;
- DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0));
- PORTB &= ~((1 << PORTB2) | (1 << PORTB1) | (1 << PORTB0));
- }
-
- bool Encoder::isPressed () {
- return (PINB & (1 << PB2)) == 0;
- }
-
- bool Encoder::getA () {
- return (PINB & (1 << PB0)) == 0;
- }
-
- bool Encoder::getB () {
- return (PINB & (1 << PB1)) == 0;
- }
-
-
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ---------------------------------------------------------------
- // PD4/T0 ... Encoder A
- // PB0 ... Encoder B
- // PD7 ... push switch of encoder (pushed = 0)
-
- void Encoder::init () {
- DDRB &= ~(1 << PB0);
- DDRD &= ~((1 << PD7) | (1 << PD4));
- PORTB |= (1 << PB0); // enable pullup
- PORTD |= (1 << PD7) | (1 << PD4); // enable pullup
- enabled = 1;
- }
-
- void Encoder::cleanup () {
- enabled = 0;
- PORTB &= ~(1 << PB0);
- PORTD &= ~((1 << PD7) | (1 << PD4));
- DDRB &= ~(1 << PB0);
- DDRD &= ~((1 << PD7) | (1 << PD4));
- }
-
- bool Encoder::isPressed () {
- return (PIND & (1 << PD7)) == 0;
- }
-
- bool Encoder::getA () {
- return (PIND & (1 << PD4)) == 0;
- }
-
- bool Encoder::getB () {
- return (PINB & (1 << PB0)) == 0;
- }
-
-#endif
-
-
-int8_t Encoder::run (uint8_t subtest) {
- switch (subtest) {
- case 0: {
- while (wait(10) == EOF) {
- printf_P(PSTR("\r => Encoder (push to clear): "));
- printf_P(PSTR("%5d (0x%02x) "), count, (uint8_t)count);
- if (isPressed()) {
- reset();
- }
- }
- return 0;
- }
- }
-
- return -1;
-}
-
-struct EncoderState {
- int8_t a:1; // signal A
- int8_t b:1; // signal B
-};
-
-void Encoder::tick100us () {
- static EncoderState lastState = { 1, 1 };
- static EncoderState lastStableState = { 1, 1 };
-
- if (!enabled) {
- count = 0;
- return;
- }
- EncoderState nextState;
- nextState.a = getA() ? 1 : 0;
- nextState.b = getB() ? 1 : 0;
- if (nextState.a == lastState.a && nextState.b == lastState.b) {
- if (lastStableState.a == 0 && nextState.b != lastStableState.b) {
- if (nextState.b == 0) {
- count = count < 127 ? count + 1 : 127;
- } else {
- count = count > -128 ? count - 1 : -128;
- }
- }
- lastStableState.a = nextState.a;
- lastStableState.b = nextState.b;
- }
- lastState.a = nextState.a;
- lastState.b = nextState.b;
-}
-
+++ /dev/null
-#ifndef ENCODER_HPP
-#define ENCODER_PP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Encoder : public TestUnit {
- public:
- uint8_t enabled;
- int8_t count;
-
- public:
- Encoder () { reset(); enabled = 0; };
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Encoder"); }
- void reset () { count = 0; }
- void tick100us ();
- bool isPressed ();
-
- private:
- bool getA ();
- bool getB ();
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <avr/pgmspace.h>
-#include <util/delay.h>
-#include <math.h>
-
-#include "i2c.hpp"
-#include "../adafruit/bme280.h"
-#include "../main.hpp"
-
-// Sparkfun https://www.sparkfun.com/products/22858
-// ENS160 address 0x53 (air quality sensor)
-// BME280 address 0x77 /humidity/temperature sensor)
-// register 0xfe: humidity_7:0
-// register 0xfd: humidity_15:8
-
-PGM_P I2c::getName () {
- switch (mode) {
- case SparkFunEnvCombo: return PSTR("I2C-Sparkfun Env-Combo");
- case Master: return PSTR("I2C-Master");
- case Slave: return PSTR("I2C-Slave");
- }
- return "?";
-}
-
-void I2c::init () {
- TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4);
- TWBR = 28; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
- TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
- TWCR = (1 << TWEN);
- ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V
- ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
- enabled = true;
-}
-
-void I2c::cleanup () {
- enabled = false;
- TWCR = (1 << TWEN);
- TWBR = 0;
- ADMUX = 0;
- ADCSRA = 0;
-}
-
-int8_t I2c::run (uint8_t subtest) {
- if (subtest == 0 && mode == I2c::SparkFunEnvCombo) {
- printf_P(PSTR(" BM280 ... "));
- if (!bm280.begin()) {
- printf_P(PSTR("E1"));
- return -1;
- }
- printf_P(PSTR("OK, ENS160 ... "));
- if (!ens160.begin()) {
- printf_P(PSTR("E2"));
- return -1;
- }
- if (!ens160.setMode(ENS160_OPMODE_STD)) {
- printf_P(PSTR("E3"));
- return -1;
- }
- if (!ens160.set_envdata(25.0, 65)) {
- printf_P(PSTR("E4"));
- return -1;
- }
-
- printf_P(PSTR("OK"));
- float accTemp = 0, accHumidity = 0;
- int8_t accCount = -1;
-
- do {
- // BME280
- float p = bm280.readPressure();
- printf_P(PSTR("\n => BM280: P= %.3fbar"), (double)p / 100000.0);
- float t = bm280.readTemperature();
- printf_P(PSTR(", T= %.2f°C"), (double)t);
- float h = bm280.readHumidity();
- printf_P(PSTR(", H= %.2f%%"), (double)h);
-
- if (accCount >= 0 && !isnanf(h) && !isnan(t)) {
- accTemp += t;
- accHumidity += h;
- accCount++;
- }
-
- bm280.setSampling(
- Adafruit_BME280::MODE_NORMAL,
- Adafruit_BME280::SAMPLING_X16,
- Adafruit_BME280::SAMPLING_X16,
- Adafruit_BME280::SAMPLING_X16,
- Adafruit_BME280::FILTER_OFF,
- Adafruit_BME280::STANDBY_MS_1000
- );
-
- // ENS160 only activated every 32s to avoid wrong temperature measuerment
- // if ES160 would be continously active, the temperature would be 4°C higher
- // -> ES160 has not enough distance to BM280
- // This solution causes only a +0.3°C higher temperatur value
- if (accCount < 0 || accCount >= 32) {
- printf_P(PSTR(" | ENS160 ("));
- if (accCount > 0) {
- h = accHumidity / accCount;
- t = accTemp / accCount;
- accTemp = 0;
- accHumidity = 0;
- }
- accCount = 0;
- if (!ens160.set_envdata(t, h)) {
- printf_P(PSTR("E1)"));
- } else {
- printf_P(PSTR("%.1f°C/%.1f%%): "), (double)t, (double)h);
- if (!ens160.setMode(ENS160_OPMODE_STD)) {
- printf_P(PSTR("E2"));
- } else {
- for (uint8_t i = 0; i < 100; i++) {
- _delay_ms(15);
- uint8_t status;
- if (ens160.readStatus(&status)) {
- if (status & ENS160_DATA_STATUS_NEWDAT) {
- ENS160_DATA data;
- if (ens160.readData(&data)) {
- printf_P(PSTR(" aqi=%d("), data.aqi);
- switch(data.aqi) {
- case 1: printf_P(PSTR("excellent")); break;
- case 2: printf_P(PSTR("good")); break;
- case 3: printf_P(PSTR("moderate")); break;
- case 4: printf_P(PSTR("poor")); break;
- case 5: printf_P(PSTR("unhealthy")); break;
- default: printf_P(PSTR("?")); break;
- }
- printf_P(PSTR("), tvoc=%dppb"), data.tvoc);
- printf_P(PSTR(", eco2=%d("), data.eco2);
- if (data.eco2 < 400) {
- printf_P(PSTR("?"));
- } else if (data.eco2 < 600) {
- printf_P(PSTR("excellent"));
- } else if (data.eco2 < 800) {
- printf_P(PSTR("good"));
- } else if (data.eco2 < 1000) {
- printf_P(PSTR("fair"));
- } else if (data.eco2 < 1500) {
- printf_P(PSTR("poor"));
- } else {
- printf_P(PSTR("bad"));
- }
- printf_P(PSTR(")"));
- }
- break;
- }
- }
- }
- }
- if (!ens160.setMode(ENS160_OPMODE_IDLE)) {
- printf_P(PSTR("E3"));
- }
- }
- }
-
- } while (wait(1000) == EOF);
-
- } else if (subtest == 0 && mode == I2c::Master) {
- if (!master.begin(0x01)) {
- printf_P(PSTR("E1"));
- return -1;
- }
- do {
- uint8_t buffer[1];
- // read poti
- ADCSRA |= (1 << ADSC); // start ADC
- while (ADCSRA & (1 << ADSC)) {} // wait for result
- buffer[0] = ADCH;
- printf_P(PSTR("\n write 0x%02x"), buffer[0]);
- if (!master.write(buffer, 1)) {
- printf_P(PSTR(" -> ERROR"));
- }
- printf_P(PSTR(", read "));
- if (master.read(buffer, 1)) {
- printf_P(PSTR("0x%02x"), buffer[0]);
- } else {
- printf_P(PSTR(" -> ERROR"));
- }
- } while (wait(1000) == EOF);
- master.end();
-
- } else if (subtest == 0 && mode == I2c::Slave) {
- if (!slave.begin(0x01, false)) {
- printf_P(PSTR("E1"));
- return -1;
- }
- do {
- int fromMaster = slave.read();
- if (fromMaster != EOF) {
- ADCSRA |= (1 << ADSC); // start ADC
- while (ADCSRA & (1 << ADSC)) {} // wait for result
- slave.write(ADCH);
- printf_P(PSTR("\n => from master: 0x%02x -> to master: 0x%02x"), fromMaster, ADCH);
- }
- } while (wait(0) == EOF);
- slave.end();
-
- } else {
- printf_P(PSTR("end"));
- return -1;
- }
- wait(500);
- return 0;
-}
-
-void I2c::handleTwiIrq () {
- if (mode == I2c::Slave) {
- DDRD |= (1 << PD7);
- PORTD |= (1 << PD7);
- slave.handleTWIIsr();
- PORTD &= ~(1 << PD7);
- } else {
- TWCR |= (1 << TWINT); // clear Interrupt Request
- }
-}
+++ /dev/null
-#ifndef I2C_HPP
-#define I2C_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include "../adafruit/bme280.h"
-#include "../adafruit/ens160.h"
-#include "../i2cmaster.hpp"
-#include "../i2cslave.hpp"
-
-
-class I2c : public TestUnit {
- public:
- typedef enum I2cMode { SparkFunEnvCombo, Master, Slave } I2cMode;
-
- private:
- I2cMode mode;
- Adafruit_BME280 bm280;
- ScioSense_ENS160 ens160;
- I2cMaster master;
- I2cSlave slave;
-
- public:
- bool enabled;
-
- public:
- I2c (I2cMode mode) { enabled = false; this->mode = mode; }
- void tick1ms () { master.tick1ms(); slave.tick1ms(); }
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName ();
- void handleTwiIrq ();
- uint16_t startRead (uint8_t address);
- uint16_t startWrite (uint8_t address);
- void stop ();
- uint16_t writeByte (uint8_t data);
- uint16_t writeData (uint8_t size, const uint8_t *data);
- uint16_t readData (uint8_t size, uint8_t *data);
- int32_t compensateBm280T (int32_t adcT);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/delay.h>
-#include <util/atomic.h>
-
-#include "ieee485.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega328P__
-
-// Nano-328P
-// ------------------------------------
-// IEE485 not supported (no UART1)
-
-void Ieee485::init () {}
-void Ieee485::cleanup () {}
-int8_t Ieee485::run (uint8_t subtest) {
- return -1;
-}
-
-#endif
-
-
-#ifdef __AVR_ATmega644P__
-
-// Nano-644
-// ------------------------------------
-// PB0 ... nRE .. Read enable
-// PB1 ... DE .. Data enable
-
-#define SET_nRE (PORTB |= (1 << PB0))
-#define CLR_nRE (PORTB &= ~(1 << PB0))
-#define SET_DE (PORTB |= (1 << PB1))
-#define CLR_DE (PORTB &= ~(1 << PB1))
-
-void Ieee485::init () {
- // Poti
- ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V
- ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
-
- // Modbus
- SET_nRE;
- CLR_DE;
- DDRB |= (1 << PB1) | (1 << PB0);
-
- // UART1 interface on Nano-644
- PORTD |= (1 << PD2); // enable RxD1 pullup
- UCSR1A = (1 << U2X1);
- UCSR1B = (1 << RXCIE1) | (1 << RXEN1) | (1 <<TXEN1);
- UCSR1C = (1 << UCSZ11) | ( 1<< UCSZ10);
- // UCSR1C |= (1 <<UPM11); // even Parity
- // UCSR1C |= (1 << UPM11) | (1 << UPM10); // odd Parity
- UBRR1H = 0;
- UBRR1L = F_CPU / 8 / 9600 - 1;
-
- enabled = 1;
-}
-
-void Ieee485::cleanup () {
- enabled = 0;
-
- ADMUX = 0;
- ADCSRA = 0;
-
- UCSR1A = 0;
- UCSR1B = 0;
- UCSR1C = 0;
- UBRR1H = 0;
- UBRR1L = 0;
- PORTD &= ~(1 << PD2);
- DDRB &= ~((1 << PB1) | (1 << PB0));
- PORTB &= ~((1 << PB1) | (1 << PB0));
-}
-
-int8_t Ieee485::run (uint8_t subtest) {
- if (subtest == 0) {
- CLR_nRE; CLR_DE;
- while (wait(500) == EOF) {
- ADCSRA |= (1 << ADSC); // start ADC
- while (ADCSRA & (1 << ADSC)) {} // wait for result
- UCSR1A |= (1 << TXC1);
- SET_nRE;
- SET_DE;
- UDR1 = ADCH;
- while ((UCSR1A & (1 << TXC1)) == 0) {}
- CLR_DE;
- CLR_nRE;
- printf_P(PSTR("\n => send Byte 0x%02x"), ADCH);
- int b;
- ATOMIC_BLOCK(ATOMIC_FORCEON) {
- b = receivedByte;
- receivedByte = -1;
- }
- if (b >= 0) {
- printf_P(PSTR("\n => receive Byte: 0x%02x"), b);
- }
- }
-
- } else {
- printf_P(PSTR("end"));
- return -1;
- }
-
- return 0;
-}
-
-void Ieee485::handleRxByte (uint8_t b) {
- receivedByte = b;
-}
-
-#endif
\ No newline at end of file
+++ /dev/null
-#ifndef IEEE485_HPP
-#define IEEE485_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Ieee485 : public TestUnit {
- public:
- uint8_t enabled;
- int16_t receivedByte;
-
- public:
- Ieee485 () { enabled = 0; receivedByte = -1; }
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual const char *getName () { return PSTR("IEEE485"); }
- void handleRxByte (uint8_t);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "lcd.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // ---------------------------------------------------------------
- // PA3 ..... E --> LCD Enable (Verbindung via J25 erforderlich)
- // PD6 ..... R/W --> Read/Write: Read=1, Write=0
- // PD7 ..... RS --> Register Select: Command=0, Data=1
- // PB7:0 ... Data --> Achtung von 5V LCD nicht lesen!
-
-
- // #define LCD_3V3
- #ifdef LCD_3V3
- #define DATA_PIN PINB
- #endif
-
- void Lcd::init () {
- DDRA |= (1 << PA3);
- DDRB = 0xff;
- DDRD |= (1 << PD7) | (1 << PD6);
- initLcd();
- #ifdef LCD_3V3
- printf_P(PSTR("init 3.3V LCD"));
- #else
- printf_P(PSTR("init 5V LCD"));
- #endif
- }
-
- void Lcd::cleanup () {
- DDRA &= ~(1 << PA3);
- DDRB = 0;
- DDRD &= ~((1 << PD7) | (1 << PD6));
- }
-
- void Lcd::setRS () { PORTD |= (1 << PD7); }
- void Lcd::clrRS () { PORTD &= ~(1 << PD7); }
- void Lcd::setRW () { PORTD |= (1 << PD6); }
- void Lcd::clrRW () { PORTD &= ~(1 << PD6); }
- void Lcd::setE () { PORTA |= (1 << PA3); }
- void Lcd::clrE () { PORTA &= ~(1 << PA3); }
-
- void Lcd::setData (uint8_t data) {
- PORTB = data;
- }
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino Nano (5V)
- // ---------------------------------------------------------------
- // PC3 ..... E --> LCD Enable (Verbindung via J25 erforderlich)
- // PD3 ..... R/W --> Read/Write: Read=1, Write=0
- // PD2 ..... RS --> Register Select: Command=0, Data=1
- // PD4 ..... Data0
- // PB0 ..... Data1
- // PD7 ..... Data2
- // PD6 ..... Data3
- // PB2 ..... Data4
- // PB3 ..... Data5
- // PB4 ..... Data6
- // PB5 ..... Data7
-
- void Lcd::init () {
- clrRW();
- clrRS();
- clrE();
- setData(0);
- DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0);
- DDRC |= (1 << PC3);
- DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2);
- initLcd();
- #ifdef LCD_3V3
- printf_P(PSTR("init 3.3V LCD"));
- #else
- printf_P(PSTR("init 5V LCD"));
- #endif
- }
-
- void Lcd::cleanup () {
- clrRW();
- clrRS();
- clrE();
- setData(0);
- DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB0));
- DDRC &= ~(1 << PC3);
- DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2));
- }
-
- void Lcd::setRS () { PORTD |= (1 << PD2); }
- void Lcd::clrRS () { PORTD &= ~(1 << PD2); }
- void Lcd::setRW () { PORTD |= (1 << PD3); }
- void Lcd::clrRW () { PORTD &= ~(1 << PD3); }
- void Lcd::setE () { PORTC |= (1 << PC3); }
- void Lcd::clrE () { PORTC &= ~(1 << PC3); }
-
- void Lcd::setData (uint8_t data) {
- if (data & 0x01) PORTD |= (1 << PD4); else PORTD &= ~((1 << PD4));
- if (data & 0x02) PORTB |= (1 << PB0); else PORTB &= ~((1 << PB0));
- if (data & 0x04) PORTD |= (1 << PD7); else PORTD &= ~((1 << PD7));
- if (data & 0x08) PORTD |= (1 << PD6); else PORTD &= ~((1 << PD6));
- if (data & 0x10) PORTB |= (1 << PB2); else PORTB &= ~((1 << PB2));
- if (data & 0x20) PORTB |= (1 << PB3); else PORTB &= ~((1 << PB3));
- if (data & 0x40) PORTB |= (1 << PB4); else PORTB &= ~((1 << PB4));
- if (data & 0x80) PORTB |= (1 << PB5); else PORTB &= ~((1 << PB5));
- }
-#endif
-
-// Befehle für das Display
-
-#define DISP_CLEAR 0b00000001 // Display clear
-#define DISP_ON 0b00001111 // Display on
-#define DISP_OFF 0b00001011 // Display off
-#define CURSOR_ON 0b00001111 // Cursor on
-#define CURSOR_OFF 0b00001101 // Cursor off
-#define BLINK_ON 0b00001111 // Cursor Blink
-#define BLINK_OFF 0b00001110 // Cursor No Blink
-
-int8_t Lcd::run (uint8_t subtest) {
- if (subtest == 0) {
- for (uint8_t i = 0; i < 20 * 4; i++) {
- char c = (char)(i + 32);
- if (i % 20 == 0) {
- setCursor(i / 20 + 1, 1);
- }
- writeData(c);
- while (isBusy()) {};
- }
- // setCursor(1, 1);
- // writeString(" 1234567890<>,;.:-_#+");
- // setCursor(2, 1);
- // writeString("abcdefghijklmnopqrst");
- // setCursor(3, 1);
- // writeString("uvwxyzABCDEFGHIJKLMN");
- // setCursor(4, 1);
- // writeString("OPQRSTUVWXYZ ");
- printf_P(PSTR("LCD beschrieben"));
- while (wait(1) == EOF) {
- }
-
- } else {
- printf_P(PSTR("end"));
- return -1;
- }
- wait(500);
- return 0;
-}
-
-void Lcd::initLcd () {
- _delay_ms(16); // min 15ms warten für Reset des Displays
-
- setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_ms(5); // min. 4.1ms
-
- setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(100); // min. 100us
-
- setData( 0b00111011 ); // 8bit Modus, 5x7 Zeichen, Mehrzeilen Display
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(100); // min. 100us
-
- writeCommand(DISP_OFF); // Display aus
- while(isBusy()) {};
- writeCommand(DISP_ON); // Display ein
- while(isBusy()) {};
- writeCommand( BLINK_OFF & CURSOR_OFF); // Blink aus und Cursor aus
- while(isBusy()) {};
- writeCommand(DISP_CLEAR);// Clear display
- while(isBusy()) {};
-}
-
-uint8_t Lcd::isBusy () {
- #ifdef LCD_3V3
- // DIR_DATA_PORT = 0;
- // SET_RW_PIN; // read
- // CLR_RS_PIN; // command
- // SET_E_PIN; // E = 1 (transfer start)
- // _delay_us(10);
- // uint8_t busy = DATA_PIN & 0x80; // read bit 7 (busy bit)
- // CLR_E_PIN; // E = 0 (transfer end)
- // CLR_RW_PIN;
- // DIR_DATA_PORT = 0xff;
- // return busy != 0;
- _delay_us(200);
- #else
- _delay_us(200);
- #endif
- return 0;
-}
-
-void Lcd::writeCommand (uint8_t cmd) {
- setData(cmd);
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- setData(0);
-}
-
-void Lcd::setDDRamAddr (uint8_t address) {
- setData(address | 0x80);
- clrRW(); // write
- clrRS(); // command
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(10); // min. 10us
- setData(0);
-}
-
-void Lcd::writeString (const char *s) {
- while (*s) {
- writeData(*s++);
- while (isBusy()) {};
- }
-}
-
-void Lcd::writeData (uint8_t data) {
- setData(data);
- setRS(); // data
- clrRW(); // write
- setE(); // E = 1 (transfer start)
- _delay_us(10); // min. 10us
- clrE(); // E = 0 (transfer end)
- _delay_us(10); // min. 10us
- clrRS();
- setData(0);
-}
-
-void Lcd::setCursor (uint8_t row, uint8_t column) {
- uint8_t b;
- if (column > 20) {
- return;
- }
- switch (row) {
- case 1: b = 0x00 + column - 1; break;
- case 2: b = 0x40 + column - 1; break;
- case 3: b = 0x14 + column - 1; break;
- case 4: b = 0x54 + column - 1; break;
- default: return;
- }
- setDDRamAddr(b);
- while (isBusy()) {};
-}
+++ /dev/null
-#ifndef LCD_HPP
-#define LCD_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Lcd : public TestUnit {
- public:
- Lcd () {};
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Lcd"); }
-
- private:
- void initLcd ();
- uint8_t isBusy ();
- void writeCommand (uint8_t);
- void setDDRamAddr (uint8_t);
- void writeString (const char *s);
- void writeData (uint8_t);
- void setCursor (uint8_t row, uint8_t column);
- void setRS ();
- void clrRS ();
- void setRW ();
- void clrRW ();
- void setE ();
- void clrE ();
- void setData (uint8_t data);
-
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "led.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // ---------------------------------------------------------------
- // PD4 ..... Red
- // PD5 ..... Orange/Yellow
- // PD6 ..... Green
- // PD7 ..... Blue
-
- void Led::init () {
- PORTD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4));
- DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4);
- }
-
- void Led::cleanup () {
- DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4));
- PORTD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5) | (1 << PD4));
- }
-
- void Led::setLed (LED led, bool on) {
- if (on) {
- switch(led) {
- case RED: PORTD |= (1 << PD4); break;
- case ORANGE: PORTD |= (1 << PD5); break;
- case GREEN: PORTD |= (1 << PD6); break;
- case BLUE: PORTD |= (1 << PD7); break;
- }
- } else {
- switch(led) {
- case RED: PORTD &= ~(1 << PD4); break;
- case ORANGE: PORTD &= ~(1 << PD5); break;
- case GREEN: PORTD &= ~(1 << PD6); break;
- case BLUE: PORTD &= ~(1 << PD7); break;
- }
- }
- }
-
- void Led::ledToggle (LED led) {
- switch(led) {
- case RED: PORTD ^= (1 << PD4); break;
- case ORANGE: PORTD ^= (1 << PD5); break;
- case GREEN: PORTD ^= (1 << PD6); break;
- case BLUE: PORTD ^= (1 << PD7); break;
- }
- }
-
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ---------------------------------------------------------------
- // PD5 ..... Red
- // PB1 ..... Orange/Yellow
- // PD3 ..... Green
- // PD2 ..... Blue
-
- void Led::init () {
- PORTD &= ~((1 << PD5) | (1 << PD3) | (1 << PD2));
- PORTB &= ~(1 << PB1);
- DDRD |= (1 << PD5) | (1 << PD3) | (1 << PD2);
- DDRB |= (1 << PB1);
- }
-
- void Led::cleanup () {
- DDRD &= ~((1 << PD5) | (1 << PD3) | (1 << PD2));
- DDRB &= ~(1 << PB1);
- PORTD &= ~((1 << PD5) | (1 << PD3) | (1 << PD2));
- PORTB &= ~(1 << PB1);
- }
-
- void Led::setLed (LED led, bool on) {
- if (on) {
- switch(led) {
- case RED: PORTD |= (1 << PD5); break;
- case ORANGE: PORTB |= (1 << PB1); break;
- case GREEN: PORTD |= (1 << PD3); break;
- case BLUE: PORTD |= (1 << PD2); break;
- }
- } else {
- switch(led) {
- case RED: PORTD &= ~(1 << PD5); break;
- case ORANGE: PORTB &= ~(1 << PB1); break;
- case GREEN: PORTD &= ~(1 << PD3); break;
- case BLUE: PORTD &= ~(1 << PD2); break;
- }
- }
- }
-
- void Led::ledToggle (LED led) {
- switch(led) {
- case RED: PORTD ^= (1 << PD5); break;
- case ORANGE: PORTB ^= (1 << PB1); break;
- case GREEN: PORTD ^= (1 << PD3); break;
- case BLUE: PORTD ^= (1 << PD2); break;
- }
- }
-
-#endif
-
-void Led::ledOn (LED led) {
- setLed(led, true);
-}
-
-void Led::ledOff (LED led) {
- setLed(led, false);
-}
-
-
-int8_t Led::run (uint8_t subtest) {
- if (subtest <= 15) {
- subtest = (subtest) % 4;
- switch (subtest) {
- case 0: ledOff(BLUE); ledOn(RED); break;
- case 1: ledOff(RED); ledOn(ORANGE); break;
- case 2: ledOff(ORANGE); ledOn(GREEN); break;
- case 3: ledOff(GREEN); ledOn(BLUE); break;
- }
- printf_P(PSTR("Test LED D%d"), subtest + 1);
- wait(500);
- return 0;
- }
-
- return -1;
-}
-
+++ /dev/null
-#ifndef LED_HPP
-#define LED_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Led : public TestUnit {
- public:
- enum LED { RED, ORANGE, GREEN, BLUE };
-
- public:
- Led () {};
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Led"); }
-
- void setLed (LED led, bool on);
- void ledOn (LED led);
- void ledOff (LED led);
- void ledToggle (LED led);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "modbus.hpp"
-#include "../main.hpp"
-
-
-#ifdef __AVR_ATmega328P__
-void Modbus::init () {}
-void Modbus::cleanup () {}
-int8_t Modbus::run (uint8_t subtest) { return -1; }
-void Modbus::handleRxByte (uint8_t b) {}
-#endif
-
-#ifdef __AVR_ATmega644P__
-
-// PB0 ... nRE .. Read enable
-// PB1 ... DE .. Data enable
-
-#define SET_nRE (PORTB |= (1 << PB0))
-#define CLR_nRE (PORTB &= ~(1 << PB0))
-#define SET_DE (PORTB |= (1 << PB1))
-#define CLR_DE (PORTB &= ~(1 << PB1))
-
-
-void Modbus::init () {
-}
-
-void Modbus::cleanup () {
- enabled = 0;
- UCSR1A = 0;
- UCSR1B = 0;
- UCSR1C = 0;
- UBRR1H = 0;
- UBRR1L = 0;
- PORTD &= ~(1 << PD2);
- DDRB &= ~((1 << PB1) | (1 << PB0));
- PORTB &= ~((1 << PB1) | (1 << PB0));
-}
-
-int8_t Modbus::run (uint8_t subtest) {
- if (subtest == 0) {
- SET_nRE;
- CLR_DE;
- DDRB |= (1 << PB1) | (1 << PB0);
-
- // UART1 interface on Nano-644
- PORTD |= (1 << PD2); // enable RxD1 pullup
- UCSR1A = (1 << U2X1);
- UCSR1B = (1 << RXCIE1) | (1 << RXEN1) | (1 <<TXEN1);
- UCSR1C = (1 << UCSZ11) | ( 1<< UCSZ10);
- // UCSR1C |= (1 <<UPM11); // even Parity
- // UCSR1C |= (1 << UPM11) | (1 << UPM10); // odd Parity
- UBRR1H = 0;
- UBRR1L = F_CPU / 8 / 9600 - 1;
-
- enabled = 1;
- printf_P(PSTR("init"));
-
- } else if (subtest >= 1 && subtest <= 4) {
- uint8_t nre, de, b;
- switch (subtest) {
- case 1: nre = 1; de = 0; b = 0x01; break;
- case 2: nre = 1; de = 1; b = 0x8e; break;
- case 3: nre = 0; de = 0; b = 0x55; break;
- case 4: nre = 0; de = 1; b = 0xaa; break;
- default: return -1;
- }
- printf_P(PSTR(" DE=%u, nRE=%u send 0x%02x... "), de, nre, b);
- if (nre) {
- SET_nRE;
- } else {
- CLR_nRE;
- }
- if (de) {
- SET_DE;
- } else {
- CLR_DE;
- }
- _delay_us(100);
- receivedBytes = 0;
- UDR1 = b;
- _delay_ms(1);
- if (receivedBytes > 0) {
- printf_P(PSTR("0x%02x received"), received[0]);
- receivedBytes = 0;
- } else {
- printf_P(PSTR("no byte received"));
- }
- printf_P(PSTR(" ... press key to proceed"));
- while (wait(0xffffffff) == EOF) {}
- CLR_DE;
- SET_nRE;
-
- } else if (subtest == 5) {
- static uint8_t frame[] = { 0x01, 0x04, 0x00, 0x00, 0x00, 0x02, 0x71, 0xcb };
- printf_P(PSTR("Modbus: lese Spannung von Eastron SDM-230 (Einphasenzähler)"));
- SET_DE;
- CLR_nRE;
- _delay_us(100);
- do {
- SET_DE;
- receivedBytes = 0;
- for (uint8_t i = 0; i < sizeof(frame); i++) {
- UCSR1A |= (1 << TXC1);
- UDR1 = frame[i];
- while ((UCSR1A & (1 <<UDRE1)) == 0) {}
- }
- while ((UCSR1A & (1 << TXC1)) == 0) {}
- CLR_DE;
- printf_P(PSTR("\n => Sending:"));
- for (uint8_t i = 0; i < sizeof(frame); i++) {
- printf_P(PSTR(" 0x%02x"), frame[i]);
- }
- int k = wait(100);
-
- printf_P(PSTR("\n RxD1:"));
- if (receivedBytes == 0) {
- printf_P(PSTR("?"));
- } else {
- for (uint8_t i = 0; i < receivedBytes; i++) {
- if (i == sizeof(frame)) {
- printf_P(PSTR(" "));
- }
- printf_P(PSTR(" 0x%02x"), received[i]);
- }
- }
- if (receivedBytes >= 16) {
- union {
- uint8_t b[4];
- float value;
- } f;
- f.b[0] = received[14];
- f.b[1] = received[13];
- f.b[2] = received[12];
- f.b[3] = received[11];
- printf_P(PSTR(" -> %4.8fV\n"), (double)f.value);
- }
- if (k != EOF) {
- break;
- }
-
- } while (wait(1000) == EOF);
-
- } else {
- printf_P(PSTR("end"));
- return -1;
- }
- wait(500);
- return 0;
-}
-
-void Modbus::handleRxByte (uint8_t b) {
- if (receivedBytes < sizeof(received)) {
- received[receivedBytes++] = b;
- }
-}
-
-#endif
\ No newline at end of file
+++ /dev/null
-#ifndef MODBUS_HPP
-#define MODBUS_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Modbus : public TestUnit {
- public:
- uint8_t enabled;
- uint8_t receivedBytes;
- uint8_t received[16];
-
-
- public:
- Modbus () { enabled = 0; receivedBytes = 0; }
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Modbus"); }
- void handleRxByte (uint8_t);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/atomic.h>
-
-#include "motor.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // ---------------------------------------------------------------
- // PB0 ..... rotation-sensor
- // PB2 ..... nFault
- // PB3 ..... PWM (OC0A)
- // PB4 ..... EN
- // PA3 ..... SW3 -> push button for Motor enable control
-
- #define ADC0K 64
-
- void Motor::init () {
- ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V
- ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
- TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00); // Fast PWM on OC0A
- // TCCR0B = (1 << CS02) | ( 1 << CS00); // f = 12 MHz / 1024 = 11,71875 kHz -> fPWM=45Hz
- TCCR0B = (1 << CS02); // f = 12 MHz / 256 = 46,875 kHz -> fPWM=183,1Hz
- DDRB |= (1 << PB4) | (1 << PB3); // Motor enable
- PORTA |= (1 << PORTA3); // push button for Motor enable control
- setEnable();
- enabled = 1;
- }
-
- void Motor::cleanup () {
- ADMUX = 0;
- ADCSRA = 0;
- TCCR0A = 0;
- TCCR0B = 0;
- DDRB &= ~((1 << PB4) | (1 << PB3));
- PORTA &= ~(1 << PORTA3);
- enabled = 0;
- }
-
- bool Motor::isSW3Pressed () {
- return (PINA & (1 << PC3)) == 0;
- }
-
- void Motor::clearEnable () {
- PORTB &= ~(1 << PB4);
- }
-
- void Motor::setEnable () {
- PORTB |= (1 << PB4);
- }
-
- bool Motor::isFaultLow () {
- return (PINB & (1 << PB2)) == 0;
- }
-
- bool Motor::isSensorHigh () {
- return (PINB & (1 << PB0)) != 0;
- }
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ---------------------------------------------------------------
- // PD4 ..... rotation-sensor
- // PD7 ..... nFault
- // PD6/OC0A ..... PWM
- // PB2 ..... EN
- // PC3 ..... SW3 -> push button for Motor enable control
-
- #define ADC0K 91
-
- void Motor::init () {
- ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=5V
- ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
- TCCR0A = (1 << COM0A1) | (1 << WGM01) | (1 << WGM00); // Fast PWM on OC0A
- // TCCR0B = (1 << CS02) | ( 1 << CS00); // f = 16 MHz / 1024 = 15,625 kHz -> fPWM=61.04Hz
- TCCR0B = (1 << CS02); // f = 16 MHz / 256 = 62.5 kHz -> fPWM=244.14Hz
- DDRB |= (1 << PB2);
- DDRC &= ~(1 << PC3);
- DDRD |= (1 << PD6);
- DDRD &= ~((1 << PD4) | (1 << PD7));
- PORTC |= ( 1 << PC3);
- PORTD |= (1 << PD7) | (1 << PD5);
- setEnable();
- enabled = 1;
- }
-
- void Motor::cleanup () {
- enabled = 0;
- ADMUX = 0;
- ADCSRA = 0;
- TCCR0A = 0;
- TCCR0B = 0;
- clearEnable();
- DDRB &= ~((1 << PB2));
- DDRC &= ~(1 << PC3);
- DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4));
- PORTC &= ~( 1 << PC3);
- PORTD &= ~((1 << PD7) | (1 << PD6));
- }
-
- bool Motor::isSW3Pressed () {
- return (PINC & (1 << PC3)) == 0;
- }
-
- void Motor::clearEnable () {
- PORTB &= ~(1 << PB2);
- }
-
- void Motor::setEnable () {
- PORTB |= (1 << PB2);
- }
-
- bool Motor::isFaultLow () {
- return (PIND & (1 << PD7)) == 0;
- }
-
- bool Motor::isSensorHigh () {
- return (PIND & (1 << PD4)) != 0;
- }
-
-#endif
-
-int8_t Motor::run (uint8_t subtest) {
- switch (subtest) {
- case 0: {
- printf_P(PSTR("\n"));
- while (wait(10) == EOF) {
-
- printf_P(PSTR("\r SW3=%d->"), isSW3Pressed() ? 0 : 1);
- if (isSW3Pressed()) {
- clearEnable();
- printf_P(PSTR("EN=0"));
- } else {
- setEnable();
- printf_P(PSTR("EN=1"));
- }
-
- ADCSRA |= (1 << ADSC); // start ADC
- while (ADCSRA & (1 << ADSC)) {} // wait for result
- printf_P(PSTR("\r => ADC0=%3d"), ADCH);
-
- ADMUX = (1 << ADLAR) | (1 << REFS1) | (1 << REFS0) | 2; // ADC2, VREF=2.5V
-
- int16_t x = ((int16_t)(ADCH) - 5) * ADC0K / 64;
- if (x < 0) x = 0; else if (x > 255) x = 255;
- uint8_t dutyCycle = 0xff - (uint8_t)x;
- if (dutyCycle <= 1) {
- dutyCycle = 0;
- } else if (dutyCycle > 254) {
- dutyCycle = 255;
- }
- OCR0A = dutyCycle;
- printf_P(PSTR(" PWM/OC0A=%3d"), dutyCycle);
-
- ADCSRA |= (1 << ADSC); // start ADC
- while (ADCSRA & (1 << ADSC)) {} // wait for result
- printf_P(PSTR(" ADC2=%3d"), ADCH);
- ADMUX = (1 << ADLAR) | (1 << REFS0); // ADC0, VREF=AVCC=3.3V
-
- printf_P(PSTR(" nFAULT=%d"), isFaultLow() ? 0 : 1);
- printf_P(PSTR(" SENSOR=%d "), isSensorHigh());
- uint16_t timer;
- ATOMIC_BLOCK(ATOMIC_FORCEON) {
- timer = rpmTimer;
- }
- float rpm = 60.0 / (float)timer / 0.0001;
- if (timer > 0) {
- printf_P(PSTR(" n= %4d U/min"), (int)rpm);
- } else {
- printf_P(PSTR(" no rotation "));
- }
-
- }
- return 0;
- }
- }
-
- return -1;
-}
-
-void Motor::tick100us () {
- static uint16_t timerH = 0;
- static uint16_t timerL = 0;
- static bool lastSensorHigh = false;
-
- bool sensorHigh = isSensorHigh();
- if (!sensorHigh && sensorHigh != lastSensorHigh && timerL > 10) {
- rpmTimer = timerL + timerH;
- timerL = 0;
- timerH = 0;
- }
- if (sensorHigh) {
- timerH = timerH < 0x4000 ? timerH + 1 : 0x4000;
- } else {
- timerL = timerL < 0x4000 ? timerL + 1 : 0x4000;
- }
- if (timerH >= 0x4000 || timerL >= 0x4000) {
- rpmTimer = 0; // no ratation detected
- }
- lastSensorHigh = sensorHigh;
-}
-
-
+++ /dev/null
-#ifndef MOTOR_HPP
-#define MOTOR_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Motor : public TestUnit {
- public:
- uint8_t enabled;
- uint16_t rpmTimer;
-
- public:
- Motor () { enabled = 0; rpmTimer = 0; };
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Motor"); }
- void tick100us ();
-
- private:
- bool isSW3Pressed ();
- void clearEnable ();
- void setEnable ();
- bool isFaultLow ();
- bool isSensorHigh ();
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "portexp.hpp"
-#include "../main.hpp"
-
-// Port-Expander MCP23S17
-
-// SN-Print Stecker IO16
-// MCP23S17 | IO16 (MEGA2560) | Ampel-Print | | MCP23S17 | IO16 (MEGA2560) | Ampel-Print |
-// ------------------------------------------ --------------------------------------------
-// GPA0 | IO16O7 (PA7) | Taster RU | | GPB0 | IO16U7 (PC7) | Taster LU |
-// GPA1 | IO16O6 (PA6) | Taster RO | | GPB1 | IO16U6 (PC6) | Taster LO |
-// GPA2 | IO16O5 (PA5) | U-Gruen | | GPB2 | IO16U5 (PC5) | R-Gruen |
-// GPA3 | IO16O4 (PA4) | U-Gelb | | GPB3 | IO16U4 (PC4) | R-Gelb |
-// GPA4 | IO16O3 (PA3) | U-Rot | | GPB4 | IO16U3 (PC3) | R-Rot |
-// GPA5 | IO16O2 (PA2) | L-Gruen | | GPB5 | IO16U2 (PC2) | O-Gruen |
-// GPA6 | IO16O1 (PA1) | L-Gelb | | GPB6 | IO16U1 (PC1) | O-Gelb |
-// GPA7 | IO16O0 (PA0) | L-Rot | | GPB7 | IO16U0 (PC0) | O-Rot |
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // --------------------------------------------------------
- // PA7 ... nCS
- // PB5 ... MOSI
- // PB6 ... MISO
- // PB7 ... SCK
-
- void PortExp::init () {
- PRR &= (1 << PRSPI);
- PORTA |= (1 << PA7);
- DDRA |= (1 << PA7); // SPI nCS
- // PORTB/DDRB must be configured before SPCR !!
- PORTB |= (1 << PB4); // nSS must be HIGH, otherwise SPI master will not become active!!
- DDRB |= (1 << PB7) | (1 << PB5) | (1 << PB4); // SPI SCK (=PB7) and SPI MOSI (=PB5)
-
- // SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=12MHz/128=93,75kHz
- SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz
- }
-
- void PortExp::cleanup () {
- DDRB &= ~(1 << PB6); // // SPI MISO (=PB6)
- DDRB &= ~((1 << PB7) | (1 << PB5)); // SPI SCK (=PB7) and SPI MOSI (=PB5)
- DDRA &= ~(1 << PA7);
- PORTA &= ~(1 << PA7); // SPI nCS
- SPCR = 0;
- }
-
- void PortExp::setChipEnable () {
- PORTA &= ~(1 << PA7);
- }
-
- void PortExp::clearChipEnable () {
- PORTA |= (1 << PA7);
- }
-
-
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ------------------------------------
- // PC1 ... nCS (MANUAL (!) connection PA1 - PA7 required)
- // PB3 ... MOSI
- // PB4 ... MISO
- // PB5 ... SCK
-
- void PortExp::init () {
- PRR &= (1 << PRSPI);
- PORTC |= (1 << PC1);
- DDRC |= (1 << PC1); // SPI nCS
- // PORTB/DDRB must be configured before SPCR !!
- PORTB |= (1 << PB2); // nSS must be HIGH, otherwise SPI master will not become active!!
- DDRB |= (1 << PB5) | (1 << PB3) | (1 << PB2); // SPI SCK (=PB5), SPI MOSI (=PB3), SPI nSS (=PB2)
-
- // SPCR |= (1 << SPE) | (1 << MSTR) | (1 << SPR1) | (1 << SPR0); // SPI enable , Master, f=16MHz/128=125kHz
- SPCR = (1 << SPE) | (1 << MSTR); // SPI enable , Master, f=12MHz/4 = 3MHz
- }
-
- void PortExp::cleanup () {
- PORTC &= ~(1 << PC1);
- DDRC &= ~(1 << PC1);
- PORTB &= ~(1 << PB2);
- DDRB &= ~((1 << PB5) | (1 << PB3) | (1 << PB2));
- SPCR = 0;
- }
-
- void PortExp::setChipEnable () {
- PORTC &= ~(1 << PC1);
- }
-
- void PortExp::clearChipEnable () {
- PORTC |= (1 << PC1);
- }
-
-#endif
-
-
-
-int8_t PortExp::writeByte (uint8_t addr, uint8_t b) {
-
- setChipEnable();
-
- SPDR = 0x40; // WRITE BYTE
- while ((SPSR & (1 << SPIF)) == 0) {}
- if (SPDR != 0) {
- printf_P(PSTR("E1"));
- clearChipEnable();
- return -1;
- }
-
- SPDR = addr; // register address
- while ((SPSR & (1 << SPIF)) == 0) {}
- if (SPDR != 0) {
- printf_P(PSTR("E2"));
- clearChipEnable();
- return -1;
- }
-
- SPDR = b; // value
- while ((SPSR & (1 << SPIF)) == 0) {}
- if (SPDR != 0) {
- printf_P(PSTR("E3"));
- clearChipEnable();
- return -1;
- }
-
- clearChipEnable();
-
- _delay_us(5);
- return 0;
-}
-
-int8_t PortExp::run (uint8_t subtest) {
- if (subtest == 0) {
- while (wait(500) == EOF) {
- printf_P(PSTR("\n => start ..."));
- for (uint8_t i = 0; i < 8; i++) {
- writeByte(0, ~(1 << i)); // IODIRA (Bank = 0)
- // writeByte(0, 0x00); // IODIRA (Bank = 0) - all output
- writeByte(0x12, (1 << i)); // GPIOA (Bank = 0)
- printf_P(PSTR("\n Bank0 - GPA%d = 1"), i);
- wait(200);
- writeByte(0x12, 0); // GPIOA (Bank = 0)
- printf_P(PSTR("\n Bank0 - GPA%d = 0"), i);
- writeByte(0, 0xff); // IODIRA (Bank = 0)
- wait(200);
- }
- for (uint8_t i = 0; i < 8; i++) {
- writeByte(1, ~(1 << i)); // IODIRB (Bank = 0)
- // writeByte(1, 0x00); // IODIRB (Bank = 0) - all output
- writeByte(0x13, (1 << i)); // GPIOB (Bank = 0)
- printf_P(PSTR("\n Bank0 - GPB%d = 1"), i);
- wait(200);
- writeByte(0x13, 0); // GPIOB (Bank = 0)
- printf_P(PSTR("\n Bank0 - GPB%d = 0"), i);
- writeByte(1, 0xff); // IODIRB (Bank = 0)
- wait(200);
- }
- }
- return 0;
- }
-
- return -1;
-}
-
+++ /dev/null
-#ifndef PORTEXP_HPP
-#define PORTEXP_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class PortExp : public TestUnit {
- public:
- PortExp () {};
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("PortExp"); }
-
- private:
- void setChipEnable ();
- void clearChipEnable ();
- int8_t writeByte (uint8_t addr, uint8_t b);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-
-#include "poti.hpp"
-#include "../main.hpp"
-
-void Poti::init () {
- ADMUX = (1 << REFS0); // ADC0, VREF=AVCC=3.3V
- ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
-}
-
-void Poti::cleanup () {
- ADMUX = 0;
- ADCSRA = 0;
-}
-
-int8_t Poti::run (uint8_t subtest) {
- switch (subtest) {
- case 0: {
- printf_P(PSTR("\n"));
- while (wait(10) == EOF) {
- printf_P(PSTR("\r => Measure ADC0: "));
- ADCSRA |= (1 << ADSC); // start ADC
- while (ADCSRA & (1 << ADSC)) {} // wait for result
- printf_P(PSTR("%4d (0x%03x)"), ADC, ADC);
- }
- return 0;
- }
- }
-
- return -1;
-}
-
-
+++ /dev/null
-#ifndef POTI_HPP
-#define POTI_PP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Poti : public TestUnit {
- public:
- Poti () {};
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Poti"); }
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-
-#include "r2r.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega644P__
- // AVCC=3.3, POTI Vmax=3.3V
- #define K 1.0
-#endif
-
-#ifdef __AVR_ATmega328P__
- // AVCC=4.7V, POTI Vmax=3.3V
- #define K (1023.0 / 738.0)
-#endif
-
-void R2r::init () {
- ADMUX = (1 << REFS0) | 2; // ADC2, VREF=AVCC=3.3V
- ADCSRA = (1 << ADEN) | 7; // ADC Enable, Prescaler 128
-}
-
-void R2r::cleanup () {
- ADMUX = 0;
- ADCSRA = 0;
-}
-
-int8_t R2r::run (uint8_t subtest) {
- switch (subtest) {
- case 0: {
- printf_P(PSTR("\n"));
- while (wait(10) == EOF) {
- printf_P(PSTR("\r => Measure ADC2: "));
- ADCSRA |= (1 << ADSC); // start ADC
- while (ADCSRA & (1 << ADSC)) {} // wait for result
- printf_P(PSTR("%4d (0x%03x)"), ADC, ADC);
- uint8_t sw = (uint8_t)( ((float)(ADC) + 32.0) / 64.0 * K );
- printf_P(PSTR(" SW9:6 = %d %d% d %d "), sw >> 3, (sw >> 2) & 0x01, (sw >> 1) & 0x01, sw & 0x01 );
- }
- return 0;
- }
- }
-
- return -1;
-}
-
-
+++ /dev/null
-#ifndef R2R_HPP
-#define R2R_PP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class R2r : public TestUnit {
- public:
- R2r () {};
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("R2R"); }
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-
-#include "rgb.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // ---------------------------------------------------------------
- // PB0 ..... Red (inverse logic -> 0 = ON)
- // PB1 ..... Green (inverse logic -> 0 = ON)
- // PB2 ..... Blue (inverse logic -> 0 = ON)
-
- void Rgb::init () {
- ledOff(RED);
- ledOff(GREEN);
- ledOff(BLUE);
- DDRB |= (1 << PB2) | (1 << PB1) | (1 << PB0);
- }
-
- void Rgb::cleanup () {
- ledOff(RED);
- ledOff(GREEN);
- ledOff(BLUE);
- DDRB &= ~((1 << PB2) | (1 << PB1) | (1 << PB0));
- }
-
- void Rgb::setLed (LED led, bool on) {
- if (on) {
- switch(led) {
- case RED: PORTB |= (1 << PB0); break;
- case GREEN: PORTB |= (1 << PB1); break;
- case BLUE: PORTB |= (1 << PB2); break;
- }
- } else {
- switch(led) {
- case RED: PORTB &= ~(1 << PB0); break;
- case GREEN: PORTB &= ~(1 << PB1); break;
- case BLUE: PORTB &= ~(1 << PB2); break;
- }
- }
- }
-
- void Rgb::ledToggle (LED led) {
- switch(led) {
- case RED: PORTB ^= (1 << PB0); break;
- case GREEN: PORTB ^= (1 << PB1); break;
- case BLUE: PORTB ^= (1 << PB2); break;
- }
- }
-
-
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ---------------------------------------------------------------
- // PD4 ..... Red (inverse logic -> 0 = ON)
- // PB0 ..... Green (inverse logic -> 0 = ON)
- // PD7 ..... Blue (inverse logic -> 0 = ON)
-
- void Rgb::init () {
- ledOff(RED);
- ledOff(GREEN);
- ledOff(BLUE);
- DDRB |= (1 << PB0);
- DDRD |= (1 << PD7) | (1 << PD4);
- }
-
- void Rgb::cleanup () {
- ledOff(RED);
- ledOff(GREEN);
- ledOff(BLUE);
- DDRB &= ~(1 << PB0);
- DDRD &= ~((1 << PD7) | (1 << PD4));
- }
-
- void Rgb::setLed (LED led, bool on) {
- if (on) {
- switch (led) {
- case RED: PORTD &= ~(1 << PD4); break;
- case GREEN: PORTB &= ~(1 << PB0); break;
- case BLUE: PORTD &= ~(1 << PD7); break;
- }
- } else {
- switch (led) {
- case RED: PORTD |= (1 << PD4); break;
- case GREEN: PORTB |= (1 << PB0); break;
- case BLUE: PORTD |= (1 << PD7); break;
- }
- }
- }
-
- void Rgb::ledToggle (LED led) {
- switch (led) {
- case RED: PORTD ^= (1 << PD4); break;
- case GREEN: PORTB ^= ~(1 << PB0); break;
- case BLUE: PORTD ^= (1 << PD7); break;
- }
- }
-
-#endif
-
-void Rgb::ledOn (LED led) {
- setLed(led, true);
-}
-
-void Rgb::ledOff (LED led) {
- setLed(led, false);
-}
-
-int8_t Rgb::run (uint8_t subtest) {
- switch (subtest) {
- case 0: {
- ledOn(RED);
- printf_P(PSTR("Red"));
- wait(3000);
- ledOff(RED);
- return 0;
- }
-
- case 1: {
- ledOn(GREEN);
- printf_P(PSTR("Green"));
- wait(3000);
- ledOff(GREEN);
- return 0;
- }
-
- case 2: {
- ledOn(BLUE);
- printf_P(PSTR("Blue"));
- wait(3000);
- ledOff(BLUE);
- return 0;
- }
-
- case 3: {
- ledOn(RED); ledOn(GREEN); ledOn(BLUE);
- printf_P(PSTR("All"));
- wait(3000);
- ledOff(RED); ledOff(GREEN); ledOff(BLUE);
- return 0;
- }
- }
-
- return -1;
-}
-
-
+++ /dev/null
-#ifndef RGB_HPP
-#define RGB_PP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Rgb : public TestUnit {
- public:
- enum LED { RED, GREEN, BLUE };
-
- public:
- Rgb () {};
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Rgb"); }
-
- void setLed (LED led, bool on);
- void ledOn (LED led);
- void ledOff (LED led);
- void ledToggle (LED led);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-
-#include "seg7.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // ---------------------------------------------------------------
-
- // PA0 ... Cathode Char 1
- // PA1 ... Cathode Char 2
- // PA2 ... Cathode Char 3
- // PA3 ... Cathode Char 4
-
- // PB0 ... Anode Segment A
- // PB1 ... Anode Segment B
- // PB2 ... Anode Segment C
- // PB3 ... Anode Segment D
- // PB4 ... Anode Segment E
- // PB5 ... Anode Segment F
- // PB6 ... Anode Segment G
- // PB7 ... Anode DP
-
- // PD5 ... nOE (Output Enable) for all LEDs
- // PD6 ... Anode L1:2
- // PD7 ... Anode L3
-
-void Seg7::init () {
- setAnodes(0);
- setCathodes(0);
- DDRA |= (1 << PA3) | (1 << PA2) | (1 << PA1) | (1 << PA0);
- DDRB = 0xff;
- DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD5);
- }
-
- void Seg7::cleanup () {
- setAnodes(0);
- setCathodes(0);
- DDRA &= ~((1 << PA3) | (1 << PA2) | (1 << PA1) | (1 << PA0));
- DDRB = 0x00;
- DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD5));
- }
-
- void Seg7::setAnodes (uint16_t a) {
- if (a & 0x0001) PORTD |= (1 << PD4); else PORTD &= ~(1 << PD4); // Anode Char A
- if (a & 0x0002) PORTB |= (1 << PB0); else PORTB &= ~(1 << PB0); // Anode Char B
- if (a & 0x0004) PORTD |= (1 << PD7); else PORTD &= ~(1 << PD7); // Anode Char C
- if (a & 0x0008) PORTD |= (1 << PD6); else PORTD &= ~(1 << PD6); // Anode Char D
- if (a & 0x0010) PORTB |= (1 << PB2); else PORTB &= ~(1 << PB2); // Anode Char E
- if (a & 0x0020) PORTB |= (1 << PB3); else PORTB &= ~(1 << PB3); // Anode Char F
- if (a & 0x0040) PORTB |= (1 << PB4); else PORTB &= ~(1 << PB4); // Anode Char G
- if (a & 0x0080) PORTB |= (1 << PB5); else PORTB &= ~(1 << PB5); // Anode Char DP
- if (a & 0x0100) PORTD |= (1 << PD3); else PORTD &= ~(1 << PD3); // Anode L1/L2
- if (a & 0x0200) PORTD |= (1 << PD2); else PORTD &= ~(1 << PD2); // Anode L3
- }
-
- void Seg7::setCathodes (uint8_t c) {
- if (c & 0x01) PORTC |= (1 << PC0); else PORTC &= ~(1 << PC0); // Chathode Char 1 (most left)
- if (c & 0x02) PORTC |= (1 << PC1); else PORTC &= ~(1 << PC1); // Chathode Char 2
- if (c & 0x04) PORTC |= (1 << PC2); else PORTC &= ~(1 << PC2); // Chathode Char 3
- if (c & 0x08) PORTC |= (1 << PC3); else PORTC &= ~(1 << PC3); // Chathode Char 4 (most right)
- }
-
- void Seg7::setOE (bool enabled) {
- if (enabled) {
- PORTB &= ~(1 << PB1);
- } else {
- PORTB |= (1 << PB1);
- }
- }
-
- void Seg7::init () {
-
- PORTB = 0;
- DDRB = 0xff;
- PORTD &= ~((1 <<PORTD7) | (1 << PORTD6));
- PORTD |= (1 << PORTD5);
- DDRD |= (1 <<DDD7) | (1 << DDD6) | (1 << DDD5);
- }
-
- void Seg7::cleanup () {
- PORTA &= ~((1 <<PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0));
- DDRA &= ~((1 <<DDA3) | (1 << DDA2) | (1 << DDA1) | (1 << DDA0));
- PORTD &= ~((1 <<PORTD7) | (1 << PORTD6) | (1 << PORTD5));
- DDRD &= ~((1 <<DDD7) | (1 << DDD6) | (1 << DDD5));
- PORTB = 0;
- DDRB = 0;
- }
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ---------------------------------------------------------------
-
- // PC0 ... Cathode Char 1
- // PC1 ... Cathode Char 2
- // PC2 ... Cathode Char 3
- // PC3 ... Cathode Char 4
-
- // PD4 ... Anode Segment A
- // PB0 ... Anode Segment B
- // PD7 ... Anode Segment C
- // PD6 ... Anode Segment D
- // PB2 ... Anode Segment E
- // PB3 ... Anode Segment F
- // PB4 ... Anode Segment G
- // PB5 ... Anode DP
-
- // PB1 ... nOE (Output Enable) for all LEDs
- // PD3 ... Anode L1:2
- // PD2 ,,, Anode L3
-
- void Seg7::init () {
- enabled = 1;
- setAnodes(0);
- setCathodes(0);
- DDRB |= (1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0) ;
- DDRC |= (1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0);
- DDRD |= (1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2);
-
- }
-
- void Seg7::cleanup () {
- enabled = 0;
- setAnodes(0);
- setCathodes(0);
- DDRB &= ~((1 << PB5) | (1 << PB4) | (1 << PB3) | (1 << PB2) | (1 << PB1) | (1 << PB0));
- DDRC &= ~((1 << PC3) | (1 << PC2) | (1 << PC1) | (1 << PC0));
- DDRD &= ~((1 << PD7) | (1 << PD6) | (1 << PD4) | (1 << PD3) | (1 << PD2));
- }
-
- void Seg7::setAnodes (uint16_t a) {
- if (a & 0x0001) PORTD |= (1 << PD4); else PORTD &= ~(1 << PD4); // Anode Char A
- if (a & 0x0002) PORTB |= (1 << PB0); else PORTB &= ~(1 << PB0); // Anode Char B
- if (a & 0x0004) PORTD |= (1 << PD7); else PORTD &= ~(1 << PD7); // Anode Char C
- if (a & 0x0008) PORTD |= (1 << PD6); else PORTD &= ~(1 << PD6); // Anode Char D
- if (a & 0x0010) PORTB |= (1 << PB2); else PORTB &= ~(1 << PB2); // Anode Char E
- if (a & 0x0020) PORTB |= (1 << PB3); else PORTB &= ~(1 << PB3); // Anode Char F
- if (a & 0x0040) PORTB |= (1 << PB4); else PORTB &= ~(1 << PB4); // Anode Char G
- if (a & 0x0080) PORTB |= (1 << PB5); else PORTB &= ~(1 << PB5); // Anode Char DP
- if (a & 0x0100) PORTD |= (1 << PD3); else PORTD &= ~(1 << PD3); // Anode L1/L2
- if (a & 0x0200) PORTD |= (1 << PD2); else PORTD &= ~(1 << PD2); // Anode L3
- }
-
- void Seg7::setCathodes (uint8_t c) {
- if (c & 0x01) PORTC |= (1 << PC0); else PORTC &= ~(1 << PC0); // Chathode Char 1 (most left)
- if (c & 0x02) PORTC |= (1 << PC1); else PORTC &= ~(1 << PC1); // Chathode Char 2
- if (c & 0x04) PORTC |= (1 << PC2); else PORTC &= ~(1 << PC2); // Chathode Char 3
- if (c & 0x08) PORTC |= (1 << PC3); else PORTC &= ~(1 << PC3); // Chathode Char 4 (most right)
- }
-
- void Seg7::setOE (bool enabled) {
- if (enabled) {
- PORTB &= ~(1 << PB1);
- } else {
- PORTB |= (1 << PB1);
- }
- }
-
-#endif
-
-const char *segName[] = { "A", "B", "C", "D", "E", "F", "G", "DP" };
-
-
-int8_t Seg7::run (uint8_t subtest) {
- if (subtest == 0) {
- setCathodes(0x0f); // all segment cathodes conected to GND
- setAnodes(0x3ff); // all segments ON
- setOE(true);
- printf_P(PSTR("ON"));
- wait(2000);
- setAnodes(0);
- return 0;
-
- } else if (subtest == 1) {
- printf_P(PSTR("OFF"));
- wait(1000);
- return 0;
-
- } else if (subtest == 2) {
- setAnodes(0x100); // L1/L2 ON
- printf_P(PSTR("L1/L2 ON"));
- wait(1000);
- setAnodes(0);
- return 0;
-
- } else if (subtest == 3) {
- setAnodes(0x200); // L3 ON
- printf_P(PSTR("L1/L2 ON"));
- wait(1000);
- setAnodes(0);
- return 0;
-
- } else if (subtest < (4 + 4 * 8)) {
- uint8_t chIndex = (subtest - 4) / 8;
- uint8_t segIndex = (subtest - 4) % 8;
- setCathodes(1 << chIndex);
- setAnodes(1 << segIndex);
- printf_P(PSTR("Char %d - %s"), chIndex, segName[segIndex]);
- wait(400);
- return 0;
- }
-
- return -1;
-}
-
-
+++ /dev/null
-#ifndef SEG7_HPP
-#define SEG7_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Seg7 : public TestUnit {
- public:
- bool enabled;
-
- public:
- Seg7 () { enabled = false; }
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Seg7"); }
-
- private:
- void setAnodes (uint16_t);
- void setCathodes (uint8_t mask);
- void setOE (bool enabled);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "switch.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega644P__
-
- // Nano-644
- // ---------------------------------------------------------------
- // PA0 ..... SW1
- // PA1 ..... SW2
- // PA2 ..... SW3
- // PA3 ..... SW4
-
- void Switch::init () {
- DDRA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0));
- PORTA |= (1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0);
- }
-
- void Switch::cleanup () {
- PORTA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0));
- DDRA &= ~((1 << PORTA3) | (1 << PORTA2) | (1 << PORTA1) | (1 << PORTA0));
- }
-
- bool Switch::isPressed (SWITCH sw) {
- switch (sw) {
- case SW1: return (PINA & ( 1 << PA0)) == 0;
- case SW2: return (PINA & ( 1 << PA1)) == 0;
- case SW3: return (PINA & ( 1 << PA2)) == 0;
- case SW4: return (PINA & ( 1 << PA3)) == 0;
- default: return false;
- }
- }
-
-#endif
-
-#ifdef __AVR_ATmega328P__
-
- // Arduino-Nano-5V
- // ---------------------------------------------------------------
- // PC0 ..... SW1
- // PC1 ..... SW2
- // PC2 ..... SW3
- // PC3 ..... SW4
-
- void Switch::init () {
- DDRC &= ~((1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0));
- PORTC |= (1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0);
- }
-
- void Switch::cleanup () {
- PORTC &= ~((1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0));
- DDRC &= ~((1 << PORTC3) | (1 << PORTC2) | (1 << PORTC1) | (1 << PORTC0));
- }
-
- bool Switch::isPressed (SWITCH sw) {
- switch (sw) {
- case SW1: return (PINC & ( 1 << PC0)) == 0;
- case SW2: return (PINC & ( 1 << PC1)) == 0;
- case SW3: return (PINC & ( 1 << PC2)) == 0;
- case SW4: return (PINC & ( 1 << PC3)) == 0;
- default: return false;
- }
- }
-
-#endif
-
-int8_t Switch::run (uint8_t subtest) {
- if (subtest < 16) {
- SWITCH sw = (SWITCH)(subtest / 4);
- switch (subtest % 4) {
- case 1: {
- if (!isPressed(sw)) {
- printf_P(PSTR("Press SW%d"), sw + 1);
- while (!isPressed(sw) && wait(0) == EOF) {}
- wait(10);
- }
- return 0;
- }
-
- case 0: case 2: {
- if (isPressed(sw)) {
- printf_P(PSTR("Release SW%d "), sw + 1);
- while (isPressed(sw) && wait(0) == EOF) {}
- wait(10);
- }
- return 0;
- }
-
- case 3: {
- return 0;
- }
- }
-
- }
-
- return -1;
-}
+++ /dev/null
-#ifndef SWITCH_HPP
-#define SWITCH_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Switch : public TestUnit {
- typedef enum { SW1 = 0, SW2 = 1, SW3 = 2, SW4 = 3 } SWITCH;
-
- public:
- Switch () {};
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Switch"); }
- bool isPressed (SWITCH sw);
-};
-
-#endif
\ No newline at end of file
+++ /dev/null
-#include <stdio.h>
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "uart1.hpp"
-#include "../main.hpp"
-
-#ifdef __AVR_ATmega328P__
- void Uart1::init () {}
- void Uart1::cleanup () {}
- int8_t Uart1::run (uint8_t subtest) { return -1; }
- void Uart1::handleRxByte (uint8_t b) {}
-#endif
-
-#ifdef __AVR_ATmega644P__
-
-int uart1_putchar(char c, FILE *stream) {
- if (c == '\n') {
- uart1_putchar('\r', stream);
- }
- loop_until_bit_is_set(UCSR1A, UDRE1);
- UDR1 = c;
- return 0;
-}
-
-static FILE mystderr = { 0, 0, _FDEV_SETUP_WRITE , 0, 0, uart1_putchar, NULL, 0 };
-
-void Uart1::cleanup () {
- enabled = 0;
- UCSR1A = 0;
- UCSR1B = 0;
- UCSR1C = 0;
- UBRR1H = 0;
- UBRR1L = 0;
- stderr = NULL;
-}
-
-int8_t Uart1::run (uint8_t subtest) {
- if (subtest == 0) {
- // UART1 interface on Nano-644
- PORTD |= (1 << PD2); // enable RxD1 pullup
- UCSR1A = (1 << U2X1);
- UCSR1B = (1 << RXCIE1) | (1 << RXEN1) | (1 <<TXEN1);
- UCSR1C = (1 << UCSZ11) | ( 1<< UCSZ10);
- UBRR1H = 0;
- UBRR1L = F_CPU / 8 / 115200 - 1;
- stderr = &mystderr;
- enabled = 1;
- printf_P(PSTR("init"));
-
- } else if (subtest == 1) {
- do {
- printf_P(PSTR("\n => send text via UART1 now..."));
- fprintf_P(stderr, PSTR("Hello UART1, ECHO-Modus active\n"));
- } while (wait(5000) == EOF);
-
- } else {
- printf_P(PSTR("end"));
- return -1;
- }
- wait(500);
- return 0;
-}
-
-void Uart1::handleRxByte (uint8_t b) {
- uart1_putchar(b, stderr);
-}
-
-#endif
\ No newline at end of file
+++ /dev/null
-#ifndef UART1_HPP
-#define UART1_HPP
-
-#include <stdint.h>
-#include "../main.hpp"
-#include <avr/pgmspace.h>
-
-class Uart1 : public TestUnit {
- public:
- uint8_t enabled;
-
- public:
- Uart1 () { enabled = 0; }
- virtual void init ();
- virtual void cleanup ();
- virtual int8_t run (uint8_t subtest);
- virtual PGM_P getName () { return PSTR("Uart1"); }
- void handleRxByte (uint8_t);
-};
-
-#endif
\ No newline at end of file