Files
Steve Karg 4781582204 Changed ATmega168 port to ATmega328 on Uno R3 with DFR0259 RS485 shield (#784)
* Changed ATmega168 example for ATmega328 on Arduino Uno R3 with DFR0259 RS485 shield. Added ADC interface from BDK port and mapped to some AV objects. Removed MS/TP MAC address DIP switch GPIO and moved MS/TP configuration to AV objects. Added AV units property. Added some Uno R3 Digital Inputs and outputs mapped to some BV. Added AVR EEPROM from BDK port and mapped some non-volatile data including MAC address and max manager and baud rate, device ID and names and description and location.
2024-09-27 14:42:47 -05:00

304 lines
7.5 KiB
C

/**
* @file
* @brief Handle Get/Set of non-volatile data
* @date July 8, 2015
* @author Steve Karg
*/
#include <stdbool.h>
#include <stdint.h>
#include "bacnet/bacint.h"
#include "bacnet/bacstr.h"
#include "nvdata.h"
#include "eeprom.h"
/**
* Gets 8-byte value from non-volatile memory
*
* @return device ID
*/
uint64_t nvdata_unsigned64(uint32_t ee_address)
{
uint64_t long_value = 0;
uint8_t buffer[8];
if (eeprom_bytes_read(ee_address, buffer, 8) == 8) {
decode_unsigned64(buffer, &long_value);
}
return long_value;
}
/**
* Sets a 8-byte value in non-volatile memory
*
* @param long_value 8-byte value
*/
int nvdata_unsigned64_set(uint32_t ee_address, uint64_t long_value)
{
uint8_t buffer[8];
encode_unsigned64(buffer, long_value);
return eeprom_bytes_write(ee_address, buffer, 8);
}
/**
* Gets a 4-byte value from non-volatile memory
*
* @return device ID
*/
uint32_t nvdata_unsigned32(uint32_t ee_address)
{
uint32_t long_value = 0;
uint8_t buffer[4];
if (eeprom_bytes_read(ee_address, buffer, 4) == 4) {
decode_unsigned32(buffer, &long_value);
}
return long_value;
}
/**
* Sets a 4-byte value in non-volatile memory
*
* @param long_value 4-byte value
*/
int nvdata_unsigned32_set(uint32_t ee_address, uint32_t long_value)
{
uint8_t buffer[4];
encode_unsigned32(buffer, long_value);
return eeprom_bytes_write(ee_address, buffer, 4);
}
/**
* Gets a 3-byte value from non-volatile memory
*
* @return device ID
*/
uint32_t nvdata_unsigned24(uint32_t ee_address)
{
uint32_t long_value = 0;
uint8_t buffer[3];
if (eeprom_bytes_read(ee_address, buffer, 3) == 3) {
decode_unsigned24(buffer, &long_value);
}
return long_value;
}
/**
* Sets a 3-byte value in non-volatile memory
*
* @param long_value 3-byte value
*/
int nvdata_unsigned24_set(uint32_t ee_address, uint32_t long_value)
{
uint8_t buffer[3];
encode_unsigned24(buffer, long_value);
return eeprom_bytes_write(ee_address, buffer, 3);
}
/**
* Gets a 2-byte value from non-volatile memory
*
* @return device ID
*/
uint16_t nvdata_unsigned16(uint32_t ee_address)
{
uint16_t short_value = 0;
uint8_t buffer[2];
if (eeprom_bytes_read(ee_address, buffer, 2) == 2) {
decode_unsigned16(buffer, &short_value);
}
return short_value;
}
/**
* Sets a 2-byte value in non-volatile memory
*
* @param short_value 2-byte value
*/
int nvdata_unsigned16_set(uint32_t ee_address, uint16_t short_value)
{
uint8_t buffer[2];
encode_unsigned16(buffer, short_value);
return eeprom_bytes_write(ee_address, buffer, 2);
}
/**
* Gets a 1-byte value from non-volatile memory
*
* @return device ID
*/
uint8_t nvdata_unsigned8(uint32_t ee_address)
{
uint8_t buffer = 0;
if (eeprom_bytes_read(ee_address, &buffer, 1) == 1) {
/* something useful */
}
return buffer;
}
/**
* Sets a 1-byte value in non-volatile memory
*
* @param byte_value 1-byte value
*/
int nvdata_unsigned8_set(uint32_t ee_address, uint8_t byte_value)
{
return eeprom_bytes_write(ee_address, &byte_value, 1);
}
bool nvdata_name_isvalid(uint8_t encoding, uint8_t length, const char *str)
{
bool valid = false;
if ((encoding < MAX_CHARACTER_STRING_ENCODING) &&
(length <= NV_EEPROM_NAME_SIZE)) {
if (encoding == CHARACTER_UTF8) {
valid = utf8_isvalid(str, length);
} else {
valid = true;
}
}
return valid;
}
/**
* @brief Write a name to the EEPROM
* @param offset - starting memory address
* @param encoding - BACnet CharacterString encoding
* @param str - string to write
* @param length - number of bytes to write
* @return true if successful
*/
bool nvdata_name_set(
uint16_t offset, uint8_t encoding, const char *str, uint8_t length)
{
uint8_t buffer[NV_EEPROM_NAME_SIZE] = { 0 };
uint8_t i = 0;
if (nvdata_name_isvalid(encoding, length, str)) {
eeprom_bytes_write(NV_EEPROM_NAME_LENGTH(offset), &length, 1);
eeprom_bytes_write(
NV_EEPROM_NAME_ENCODING(offset), (uint8_t *)&encoding, 1);
for (i = 0; i < length; i++) {
buffer[i] = str[i];
}
eeprom_bytes_write(
NV_EEPROM_NAME_STRING(offset), &buffer[0], NV_EEPROM_NAME_SIZE);
return true;
}
return false;
}
/**
* @brief Save the BACnet CharacterString to non-volatile memory at offset
* @param offset - starting memory address
* @param char_string - BACnet CharacterString value
* @param error_class - BACnet error class
* @param error_code - BACnet error code
* @return true if name is a valid set of characters, valid length, and
* valid character set encoding.
* error_code and error_class are filled if false.
*/
bool nvdata_name_write(
uint32_t offset,
BACNET_CHARACTER_STRING *char_string,
BACNET_ERROR_CLASS *error_class,
BACNET_ERROR_CODE *error_code)
{
bool status = false;
size_t length;
uint8_t encoding;
const char *str;
length = characterstring_length(char_string);
if (length <= NV_EEPROM_NAME_SIZE) {
encoding = characterstring_encoding(char_string);
if (encoding < MAX_CHARACTER_STRING_ENCODING) {
str = characterstring_value(char_string);
status = nvdata_name_set(offset, encoding, str, length);
if (!status) {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_VALUE_OUT_OF_RANGE;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED;
}
} else {
*error_class = ERROR_CLASS_PROPERTY;
*error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY;
}
return status;
}
/**
* @brief Read a name from the EEPROM
* @param offset - starting memory address
* @param char_string - BACnet CharacterString value
* @param default_string - default string to use if not valid
*/
void nvdata_name(
uint32_t offset,
BACNET_CHARACTER_STRING *char_string,
const char *default_string)
{
uint8_t encoding = 0;
uint8_t length = 0;
char name[NV_EEPROM_NAME_SIZE + 1] = "";
eeprom_bytes_read(NV_EEPROM_NAME_ENCODING(offset), &encoding, 1);
eeprom_bytes_read(NV_EEPROM_NAME_LENGTH(offset), &length, 1);
eeprom_bytes_read(
NV_EEPROM_NAME_STRING(offset), (uint8_t *)&name, NV_EEPROM_NAME_SIZE);
if (nvdata_name_isvalid(encoding, length, name)) {
characterstring_init(char_string, encoding, &name[0], length);
} else if (default_string) {
(void)nvdata_name_set(
offset, CHARACTER_UTF8, default_string, strlen(default_string));
characterstring_init_ansi(char_string, default_string);
}
}
/**
* Read bytes from SEEPROM memory at address
*
* @param start_address - SEEPROM starting memory address
* @param buffer - place to store data that has been read
* @param length - number of bytes to read
*
* @return number of bytes read, or 0 on error
*/
uint32_t nvdata_get(uint32_t ee_address, uint8_t *buffer, uint32_t nbytes)
{
return eeprom_bytes_read(ee_address, buffer, nbytes);
}
/**
* Write some data and wait until it is sent
*
* @param ee_address - SEEPROM starting memory address
* @param buffer - data to send
* @param length - number of bytes of data
*
* @return number of bytes written, or 0 on error
*/
uint32_t
nvdata_set(uint32_t ee_address, uint8_t *buffer, uint32_t buffer_length)
{
return eeprom_bytes_write(ee_address, buffer, buffer_length);
}