/** * \brief Main function. * * Initializes the board, and runs the application in an infinite loop. */ int main(void) { /* hardware initialization */ sysclk_init(); board_init(); pmic_init(); timer_init(); rs485_init(); led_init(); adc_init(); #ifdef CONF_BOARD_ENABLE_RS485_XPLAINED // Enable display backlight gpio_set_pin_high(NHD_C12832A1Z_BACKLIGHT); #endif // Workaround for known issue: Enable RTC32 sysclk sysclk_enable_module(SYSCLK_PORT_GEN, SYSCLK_RTC); while (RTC32.SYNCCTRL & RTC32_SYNCBUSY_bm) { // Wait for RTC32 sysclk to become stable } cpu_irq_enable(); /* application initialization */ rs485_baud_rate_set(38400); bacnet_init(); /* run forever - timed tasks */ timer_callback(bacnet_task_timed, 5); for (;;) { bacnet_task(); led_task(); } }
/************************************************************************* * Description: Initialize the room network USART * Returns: nothing * Notes: none **************************************************************************/ void rs485_init( void) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; GPIO_StructInit(&GPIO_InitStructure); /* Configure USARTx Rx as input floating */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure USARTx Tx as alternate function push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Configure the Request To Send (RTS) aka Transmit Enable pin */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); /* Enable USARTx Clock */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); /*RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);*/ /* Enable GPIO Clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* Enable the USART Pins Software Remapping for this pair of pins and peripheral functions: USART3 Full remap (TX/PD8, RX/PD9, CK/PD10, CTS/PD11, RTS/PD12) */ /*GPIO_PinRemapConfig(GPIO_FullRemap_USART3, ENABLE);*/ /* Configure the NVIC Preemption Priority Bits */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); /* Enable the USARTx Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); /* enable the USART to generate interrupts */ USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); rs485_baud_rate_set(Baud_Rate); USART_Cmd(USART2, ENABLE); FIFO_Init(&Receive_Buffer, &Receive_Buffer_Data[0], (unsigned) sizeof(Receive_Buffer_Data)); timer_elapsed_start(&Silence_Timer); }
bool Device_Write_Property_Local( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value - false=error */ int len = 0; BACNET_APPLICATION_DATA_VALUE value; uint8_t max_master = 0; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_OBJECT_LIST) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch ((int) wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type. Object_Id.instance))) { eeprom_bytes_write(NV_EEPROM_DEVICE_0, (uint8_t *) & value.type.Object_Id.instance, 4); /* we could send an I-Am broadcast to let the world know */ status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { max_master = value.type.Unsigned_Int; dlmstp_set_max_master(max_master); eeprom_bytes_write(NV_EEPROM_MAX_MASTER, &max_master, 1); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_NAME: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { status = bacnet_name_write_unique(NV_EEPROM_DEVICE_NAME, wp_data->object_type, wp_data->object_instance, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_DESCRIPTION: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { status = bacnet_name_write(NV_EEPROM_DEVICE_DESCRIPTION, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_LOCATION: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { status = bacnet_name_write(NV_EEPROM_DEVICE_LOCATION, &value.type.Character_String, &wp_data->error_class, &wp_data->error_code); } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case 9600: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int <= 115200) && (rs485_baud_rate_set(value.type.Unsigned_Int))) { status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_TYPE: case PROP_VENDOR_NAME: case PROP_FIRMWARE_REVISION: case PROP_APPLICATION_SOFTWARE_VERSION: case PROP_DAYLIGHT_SAVINGS_STATUS: case PROP_PROTOCOL_VERSION: case PROP_PROTOCOL_REVISION: case PROP_PROTOCOL_SERVICES_SUPPORTED: case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED: case PROP_OBJECT_LIST: case PROP_MAX_APDU_LENGTH_ACCEPTED: case PROP_SEGMENTATION_SUPPORTED: case PROP_DEVICE_ADDRESS_BINDING: case PROP_DATABASE_REVISION: case 512: case 513: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } return status; }
void test_task( void) { uint8_t data_register = 0; uint16_t id = 0; if (timer_interval_expired(&Test_Timer)) { timer_interval_reset(&Test_Timer); sprintf(Send_Buffer, "BACnet: 0000000\r\n"); MSTP_MAC_Address = input_address(); Send_Buffer[8] = (MSTP_MAC_Address & BIT0) ? '1' : '0'; Send_Buffer[9] = (MSTP_MAC_Address & BIT1) ? '1' : '0'; Send_Buffer[10] = (MSTP_MAC_Address & BIT2) ? '1' : '0'; Send_Buffer[11] = (MSTP_MAC_Address & BIT3) ? '1' : '0'; Send_Buffer[12] = (MSTP_MAC_Address & BIT4) ? '1' : '0'; Send_Buffer[13] = (MSTP_MAC_Address & BIT5) ? '1' : '0'; Send_Buffer[14] = (MSTP_MAC_Address & BIT6) ? '1' : '0'; serial_bytes_send((uint8_t *) Send_Buffer, 17); } if (serial_byte_get(&data_register)) { /* echo the character */ serial_byte_send(data_register); switch (data_register) { case '0': Binary_Output_Present_Value_Set(0, BINARY_INACTIVE, 0); Binary_Output_Present_Value_Set(1, BINARY_INACTIVE, 0); break; case '1': Binary_Output_Present_Value_Set(0, BINARY_ACTIVE, 0); Binary_Output_Present_Value_Set(1, BINARY_ACTIVE, 0); break; case '2': Binary_Output_Present_Value_Set(0, BINARY_NULL, 0); Binary_Output_Present_Value_Set(1, BINARY_NULL, 0); break; case '3': rs485_baud_rate_set(38400); break; case '5': rs485_baud_rate_set(57600); break; case '7': rs485_baud_rate_set(76800); break; case '9': rs485_baud_rate_set(9600); break; case 'e': seeprom_bytes_read(NV_SEEPROM_TYPE_0, (uint8_t *) & id, 2); sprintf(Send_Buffer, "\r\n%04X", id); serial_bytes_send((uint8_t *) Send_Buffer, strlen(Send_Buffer)); break; case 'b': sprintf(Send_Buffer, "\r\n%lubps", (unsigned long) rs485_baud_rate()); serial_bytes_send((uint8_t *) Send_Buffer, strlen(Send_Buffer)); break; case 'm': sprintf(Send_Buffer, "\r\nMax:%u", (unsigned) dlmstp_max_master()); serial_bytes_send((uint8_t *) Send_Buffer, strlen(Send_Buffer)); break; default: break; } serial_byte_send('\r'); serial_byte_send('\n'); serial_byte_transmit_complete(); } test_pin_toggle(); }
bool Device_Write_Property_Local( BACNET_WRITE_PROPERTY_DATA * wp_data) { bool status = false; /* return value - false=error */ int len = 0; uint8_t encoding = 0; size_t length = 0; BACNET_APPLICATION_DATA_VALUE value; /* decode the some of the request */ len = bacapp_decode_application_data(wp_data->application_data, wp_data->application_data_len, &value); /* FIXME: len < application_data_len: more data? */ if (len < 0) { /* error while decoding - a value larger than we can handle */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; return false; } if ((wp_data->object_property != PROP_OBJECT_LIST) && (wp_data->array_index != BACNET_ARRAY_ALL)) { /* only array properties can have array options */ wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_PROPERTY_IS_NOT_AN_ARRAY; return false; } switch (wp_data->object_property) { case PROP_OBJECT_IDENTIFIER: if (value.tag == BACNET_APPLICATION_TAG_OBJECT_ID) { if ((value.type.Object_Id.type == OBJECT_DEVICE) && (Device_Set_Object_Instance_Number(value.type. Object_Id.instance))) { /* we could send an I-Am broadcast to let the world know */ status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_INFO_FRAMES: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if (value.type.Unsigned_Int <= 255) { dlmstp_set_max_info_frames(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_MAX_MASTER: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int > 0) && (value.type.Unsigned_Int <= 127)) { dlmstp_set_max_master(value.type.Unsigned_Int); status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_NAME: if (value.tag == BACNET_APPLICATION_TAG_CHARACTER_STRING) { length = characterstring_length(&value.type.Character_String); if (length < 1) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } else if (length < characterstring_capacity(&My_Object_Name)) { encoding = characterstring_encoding(&value.type.Character_String); if (encoding < MAX_CHARACTER_STRING_ENCODING) { /* All the object names in a device must be unique. */ if (Device_Valid_Object_Name(&value.type. Character_String, NULL, NULL)) { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_DUPLICATE_NAME; } else { Device_Set_Object_Name(&value.type. Character_String); status = true; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_CHARACTER_SET_NOT_SUPPORTED; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_NO_SPACE_TO_WRITE_PROPERTY; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case 9600: if (value.tag == BACNET_APPLICATION_TAG_UNSIGNED_INT) { if ((value.type.Unsigned_Int <= 115200) && (rs485_baud_rate_set(value.type.Unsigned_Int))) { status = true; } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_VALUE_OUT_OF_RANGE; } } else { wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_INVALID_DATA_TYPE; } break; case PROP_OBJECT_TYPE: case PROP_VENDOR_NAME: case PROP_VENDOR_IDENTIFIER: case PROP_MODEL_NAME: case PROP_FIRMWARE_REVISION: case PROP_APPLICATION_SOFTWARE_VERSION: case PROP_PROTOCOL_VERSION: case PROP_PROTOCOL_REVISION: case PROP_PROTOCOL_SERVICES_SUPPORTED: case PROP_PROTOCOL_OBJECT_TYPES_SUPPORTED: case PROP_OBJECT_LIST: case PROP_MAX_APDU_LENGTH_ACCEPTED: case PROP_SEGMENTATION_SUPPORTED: case PROP_DEVICE_ADDRESS_BINDING: case PROP_ACTIVE_COV_SUBSCRIPTIONS: case PROP_DATABASE_REVISION: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_WRITE_ACCESS_DENIED; break; default: wp_data->error_class = ERROR_CLASS_PROPERTY; wp_data->error_code = ERROR_CODE_UNKNOWN_PROPERTY; break; } /* not using len at this time */ len = len; return status; }