Selaa lähdekoodia

Работа с ringfs.

TelenkovDmitry 10 kuukautta sitten
vanhempi
commit
2a50eb399b

+ 202 - 25
fw/modules/log/log.c

@@ -5,23 +5,23 @@
 #include "FreeRTOS.h"
 #include "task.h"
 #include "semphr.h"
+#include "rtc.h"
 #include <string.h>
-
-
+#include <stdio.h>
+#include <inttypes.h>
 
 #undef DBG
 #define DBG if(1)
 
 
 
-#define LOG_ENTRY_VERSION 1
-
-#define LOG_FLASH_SECTOR_OFFSET	4
+static struct ringfs fs_log;
+static struct ringfs fs_archive;
 
-#define ALARM_LOG_FLASH_SECTOR_OFFSET	258
-#define SECTOR_COUNT (spi_flash_desc.sector_count/2 - LOG_FLASH_SECTOR_OFFSET)
+static SemaphoreHandle_t log_mutex;
 
 
+//
 static int op_sector_erase(struct ringfs_flash_partition *flash, int address) {
 	(void)flash;
 	int ret;
@@ -29,6 +29,7 @@ static int op_sector_erase(struct ringfs_flash_partition *flash, int address) {
 	return ret;
 }
 
+//
 static ssize_t op_program(struct ringfs_flash_partition *flash, int address, const void *data, size_t size) {
 	(void)flash;
 	int ret;
@@ -36,6 +37,7 @@ static ssize_t op_program(struct ringfs_flash_partition *flash, int address, con
 	return ret;
 }
 
+//
 static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *data, size_t size) {
 	(void)flash;
 	int ret;
@@ -43,8 +45,8 @@ static ssize_t op_read(struct ringfs_flash_partition *flash, int address, void *
 	return ret;
 }
 
-
-static struct ringfs_flash_partition ringfs_flash = 
+//
+static struct ringfs_flash_partition ringfs_flash_log = 
 {
 	.sector_offset = LOG_FLASH_SECTOR_OFFSET,
 	.sector_erase = op_sector_erase,
@@ -52,17 +54,15 @@ static struct ringfs_flash_partition ringfs_flash =
 	.read = op_read,
 };
 
-static struct ringfs fs;
-
-static struct ringfs_flash_partition ringfs_flash2 = 
+//
+static struct ringfs_flash_partition ringfs_flash_archive = 
 {
-	.sector_offset = ALARM_LOG_FLASH_SECTOR_OFFSET,
+	.sector_offset = ARCHIVE_FLASH_SECTOR_OFFSET,
 	.sector_erase = op_sector_erase,
 	.program = op_program,
 	.read = op_read,
 };
 
-static struct ringfs fs2;
 
 
 //
@@ -73,32 +73,209 @@ void log_init(bool format)
 	if (!spi_flash_desc.present)
 		return;
     
-	ringfs_flash.sector_size = spi_flash_desc.sector_size;
-	ringfs_flash.sector_count = SECTOR_COUNT;
+    // ---------------------------------------------------------------------- //
+    // Журнал
+        
+	ringfs_flash_log.sector_size = spi_flash_desc.sector_size;
+	ringfs_flash_log.sector_count = LOG_FLASH_SECTOR_COUNT;
 
-	ringfs_init(&fs, &ringfs_flash, LOG_ENTRY_VERSION, sizeof(log_entry_t));
-	if (format || ringfs_scan(&fs) != 0){
+	ringfs_init(&fs_log, &ringfs_flash_log, LOG_ENTRY_VERSION, sizeof(log_entry_t));
+    
+	if (format || ringfs_scan(&fs_log) != 0) {
 		DBG printf("FAT1 false\r\n");
-		ringfs_format(&fs);
+		ringfs_format(&fs_log);
 	}
 	DBG printf("FAT1 true\r\n");
-	ringfs_flash2.sector_size = spi_flash_desc.sector_size;
-	ringfs_flash2.sector_count = SECTOR_COUNT;
+    
+    // ---------------------------------------------------------------------- //
+    // Архив
+    
+	ringfs_flash_archive.sector_size = spi_flash_desc.sector_size;
+	ringfs_flash_archive.sector_count = ARCHIVE_FLASH_SECTOR_COUNT;
 
-	ringfs_init(&fs2, &ringfs_flash2, LOG_ENTRY_VERSION, sizeof(log_entry_t));
-	if (format || ringfs_scan(&fs2) != 0){
+	ringfs_init(&fs_archive, &ringfs_flash_archive, ARCHIV_ENTRY_VERSION, sizeof(archive_entry_t));
+    
+	if (format || ringfs_scan(&fs_archive) != 0) {
 		DBG printf("FAT2 false\r\n");
-		ringfs_format(&fs2);
+		ringfs_format(&fs_archive);
 	}
 	DBG printf("FAT2 true\r\n");
 	
+    // ---------------------------------------------------------------------- //
+    
     //fLogInit = true;
 
-	//log_mutex = xSemaphoreCreateMutex();
+	log_mutex = xSemaphoreCreateMutex();
 
 	//xTaskCreate(log_task, ( char * ) "log_task", configMINIMAL_STACK_SIZE * 2, NULL, tskIDLE_PRIORITY, NULL);
 }
 
+//
+int log_fetch(void *entry, entry_type_t entry_type, uint32_t timeout) 
+{
+    int ret;
+    
+    ret = xSemaphoreTake(log_mutex, (TickType_t)timeout);
+    
+    if (ret == pdFALSE)
+        return ret;
+    if (entry_type == LOG_ENTRY)
+        ret = ringfs_fetch(&fs_log, entry);
+    else if (entry_type == ARCHIVE_ENTRY)
+        ret = ringfs_fetch(&fs_archive, entry);
+    else ret = -1;
+
+    xSemaphoreGive(log_mutex);
+    return ret;   
+}
+
+//
+int log_discard(void *entry, entry_type_t entry_type, uint32_t timeout)
+{
+    int ret;
+      
+    ret = xSemaphoreTake(log_mutex, (TickType_t)timeout);
+    
+    if (ret == pdFALSE)
+        return ret;
+    if (entry_type == LOG_ENTRY)
+        ret = ringfs_discard(&fs_log);
+    else if (entry_type == ARCHIVE_ENTRY)
+        ret = ringfs_discard(&fs_archive);
+    else ret = -1;
+    
+    xSemaphoreGive(log_mutex);
+    return ret; 
+}
+
+// TODO unixtime ms
+int log_append(void *entry, entry_type_t entry_type)
+{
+    int ret;
+    TM_RTC_t time;
+    common_entry_t *entry_ptr = entry;
+    
+    ret = xSemaphoreTake(log_mutex, portMAX_DELAY);
+    
+    if (ret == pdFALSE)
+        return ret;
+    if (!entry_ptr->timestamp) {
+        TM_RTC_GetDateTime(&time, TM_RTC_Format_BIN);
+        entry_ptr->timestamp = time.unix;
+    }
+    if (entry_type == LOG_ENTRY)
+        ret = ringfs_append(&fs_log, entry);
+    else if (entry_type == ARCHIVE_ENTRY)
+        ret = ringfs_append(&fs_archive, entry);
+    else ret = -1;
+    
+    xSemaphoreGive(log_mutex);
+    return ret;
+    
+}
+
+// -------------------------------------------------------------------------- //
+// Tests
+
+#if 0
+// fs_log
+int log_test(void)
+{
+    int ret;
+    
+}
+#endif
+
+
+// fs_archive
+int test_archive(void)
+{
+    int ret;
+    archive_entry_t entry;
+    int capacity_flash = 0;
+    int count_flash = 0;
+    
+    capacity_flash = ringfs_capacity(&fs_archive);
+    count_flash = ringfs_count_exact(&fs_archive);
+      
+    DBG printf("Fetching...\r\n");
+    
+    
+    
+    if (log_fetch(&entry, ARCHIVE_ENTRY, portMAX_DELAY)) 
+    {
+        printf("%" PRId64 "\n", entry.timestamp);
+    }
+    else 
+    {
+        DBG printf("fail\r\n");
+    }
+#if 0    
+    DBG printf("Discarding\r\n");
+    if (log_discard)
+#endif    
+    return 0;
+}
+
+
+
+// Добавить n архивных записей
+int test_add_random_archive_entry(uint32_t cnt_entry)
+{
+    int ret;
+    archive_entry_t entry;
+    
+    DBG printf("Try append %u archive entry\r\n", cnt_entry);
+
+    for (uint32_t i = 0; i < cnt_entry; i++)
+    {
+        entry.input_value = ringfs_count_exact(&fs_archive);
+        entry.crc = 0xAB;
+        
+        ret = log_append(&entry, ARCHIVE_ENTRY);
+    }
+    return ret;
+}
+
+
+
+//
+void test_fetch(void)
+{
+    archive_entry_t entry = {0};
+    log_fetch(&entry, ARCHIVE_ENTRY, portMAX_DELAY);
+    printf("[entry] timestamp = %u, value = %u, crc = %u\r\n", (uint32_t)entry.timestamp, entry.input_value, entry.crc);
+}
+
+//
+void test_archive_info(void)
+{
+    int capacity_flash = 0;
+    int count_flash = 0;
+    int count_estimate = 0;
+    
+    capacity_flash = ringfs_capacity(&fs_archive);
+    count_flash = ringfs_count_exact(&fs_archive);
+    count_estimate = ringfs_count_estimate(&fs_archive);
+    
+    printf("Archive partition capasity: %u\r\n", capacity_flash);
+    printf("Count archive entry: %u\r\n", count_flash);
+    printf("Estimate count: %u\r\n", count_estimate);
+}
+
+//
+void test_archive_format(void)
+{
+    ringfs_format(&fs_archive);
+}
+
+
+
+
+
+
+
+
 
 
 

+ 59 - 1
fw/modules/log/log.h

@@ -5,6 +5,22 @@
 #include <stdbool.h>
 
 
+#define LOG_ENTRY_VERSION               1
+
+#define ARCHIV_ENTRY_VERSION            1
+
+#define LOG_FLASH_SECTOR_OFFSET         4
+
+#define LOG_FLASH_SECTOR_COUNT          252
+
+#define ARCHIVE_FLASH_SECTOR_OFFSET     260
+
+#define ARCHIVE_FLASH_SECTOR_COUNT      252
+
+#define SECTOR_COUNT (spi_flash_desc.sector_count/2 - LOG_FLASH_SECTOR_OFFSET)
+
+
+//
 typedef enum 
 {
     LOG_SYSTEM_BOOT = 0,			// device booted
@@ -35,21 +51,63 @@ typedef enum
 } log_type_t;
 
 
+typedef enum
+{
+    LOG_ENTRY = 0,
+    ARCHIVE_ENTRY,
+    
+} entry_type_t;
+
+
+typedef __packed struct 
+{
+    uint64_t timestamp;
+    
+} common_entry_t;
 
+//
 typedef __packed struct 
 {
-	uint32_t timestamp;
+	uint64_t timestamp;
 	log_type_t type:8;
 	char data[50];
     
 } log_entry_t;
 
 
+typedef __packed struct
+{
+    uint64_t timestamp;
+    uint8_t input_value;
+    uint8_t crc;
+} archive_entry_t;
+
 
 
 void log_init(bool format);
 
 
+// -------------------------------------------------------------------------- //
+// Tests
+
+// fs_log
+int log_test(void);
+
+// fs_archive
+int test_archive(void);
+
+//
+int test_add_random_archive_entry(uint32_t cnt_entry);
+
+//
+void test_archive_info(void);
+
+//
+void test_fetch(void);
+
+//
+void test_archive_format(void);
+
 
 #if 0
 

+ 358 - 379
fw/modules/misc/rtc.c

@@ -1,379 +1,358 @@
-#include "rtc.h"
-#include "lwip/apps/sntp.h"
-#include "settings_api.h"
-#include <string.h>
-
-
-//TM_RTC_t calendar;
-
-/* Days in a month */
-uint8_t TM_RTC_Months[2][12] = {
-	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},	/* Not leap year */
-	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}	/* Leap year */
-};
-
-// monthly correction data sheet
-const uint8_t table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
-
-// monmonth data table of common year
-const uint8_t mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-/* Internal RTC defines */
-#define TM_RTC_LEAP_YEAR(year) 			((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
-#define TM_RTC_DAYS_IN_YEAR(x)			TM_RTC_LEAP_YEAR(x) ? 366 : 365
-#define TM_RTC_OFFSET_YEAR				1970
-#define TM_RTC_SECONDS_PER_DAY			86400
-#define TM_RTC_SECONDS_PER_HOUR			3600
-#define TM_RTC_SECONDS_PER_MINUTE		60
-#define TM_RTC_BCD2BIN(x)				((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))
-#define TM_RTC_CHAR2NUM(x)				((x) - '0')
-#define TM_RTC_CHARISNUM(x)				((x) >= '0' && (x) <= '9')
-
-
-extern SemaphoreHandle_t flash_mutex;
-
-
-
-/**
-  * @brief  rtc peripheral initialization.
-  * @param  calendar
-  * @retval 0: rtc already init
-            1: rtc init
-  */
-uint8_t TM_RTC_Init(void)
-{
-    TM_RTC_t datatime;
-    
-    // enable pwc and bpr clocks
-    crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
-    crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
-    
-    // enable the battery-powered domain write operations
-    pwc_battery_powered_domain_access(TRUE);
-    
-    // check if rtc is initialized 
-    if (bpr_data_read(BPR_DATA4) != 0x1234)
-    {
-        // reset battery-powered domain register
-        bpr_reset();
-        
-        // enable the lext osc
-        crm_clock_source_enable(CRM_CLOCK_SOURCE_LEXT, TRUE);
-        // wait lext is ready
-        while(crm_flag_get(CRM_LEXT_STABLE_FLAG) == RESET);
-        // select the rtc clock source
-        crm_rtc_clock_select(CRM_RTC_CLOCK_LEXT);
-        
-        // enable rtc clock
-        crm_rtc_clock_enable(TRUE);
-        
-        // wait for rtc registers update 
-        rtc_wait_update_finish();
-        
-        // wait for the register write to complete
-        rtc_wait_config_finish();
-        
-        // set rtc divider: set rtc period to 1sec 
-        rtc_divider_set(32767);
-        
-        // wait for the register write to complete
-        rtc_wait_config_finish();
-        
-        // set date and time
-        datatime.date    = 1;
-        datatime.day     = 1;
-        datatime.month   = 1;
-        datatime.year    = 0;
-        datatime.hours   = 0;
-        datatime.minutes = 0;
-        datatime.seconds = 0;
-        
-        TM_RTC_SetDateTime(&datatime);
-        
-        // writes data to bpr register 
-        bpr_data_write(BPR_DATA4, 0x1234);
-        
-        return 1;
-    }
-    else
-    {
-        // wait for rtc registers update
-        rtc_wait_update_finish();
-
-        // wait for the register write to complete
-        rtc_wait_config_finish();
-    
-        return 0;    
-    }
-}
-
-
-//
-void TM_RTC_SetDataTimeUnix(uint32_t unixTime)
-{
-    TM_RTC_t data;
-  
-    TM_RTC_GetDateTimeFromUnix(&data, unixTime);
-    rtc_counter_set(unixTime);
-    rtc_wait_config_finish();
-}
-
-
-/**
-  * @brief  set time. convert the input clock to a second.
-  *         the time basic : 1970.1.1
-  *         legitimate year: 1970 ~ 2099
-  * @param  calendar
-  * @retval 0: set time right.
-  *         1: set time failed.
-  */
-TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data)
-{
-    uint32_t seccount = 0;
-    
-    if (data->year > 99 || 
-		data->month == 0 || 
-		data->month > 12 ||
-		data->date == 0 ||
-		data->date > TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + data->year) ? 1 : 0][data->month - 1] ||
-		data->hours > 23 ||
-		data->minutes > 59 ||
-		data->seconds > 59 ||
-		data->day == 0 ||
-		data->day > 7) 
-    {
-		return TM_RTC_Result_Error; 
-	}
-    
-    // enable pwc and bpr clocks
-    crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
-    crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
-    
-    // enable write access to bpr domain
-    pwc_battery_powered_domain_access(TRUE);
-    
-    // set the rtc counter value
-    seccount = TM_RTC_GetUnixTimeStamp(data);
-    rtc_counter_set(seccount);
-    
-    // wait for the register write to complete
-    rtc_wait_config_finish();
-    
-    return TM_RTC_Result_Ok;
-}
-
-
-//
-TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str) 
-{
-	TM_RTC_t tmp;
-	uint8_t i = 0;
-	
-	// Get date
-	tmp.date = 0;
-	while (TM_RTC_CHARISNUM(*(str + i))) {
-		tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
-		i++;
-	}
-	i++;
-	
-	// Get month
-	tmp.month = 0;
-	while (TM_RTC_CHARISNUM(*(str + i))) {
-		tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
-		i++;
-	}
-	i++;
-	
-	// Get year
-	tmp.year = 0;
-	while (TM_RTC_CHARISNUM(*(str + i))) {
-		tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
-		i++;
-	}
-	i++;
-	
-	// Get day in a week
-	tmp.day = 0;
-	while (TM_RTC_CHARISNUM(*(str + i))) {
-		tmp.day = tmp.day * 10 + TM_RTC_CHAR2NUM(*(str + i));
-		i++;
-	}
-	i++;
-	
-	// Get hours
-	tmp.hours = 0;
-	while (TM_RTC_CHARISNUM(*(str + i))) {
-		tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
-		i++;
-	}
-	i++;
-	
-	// Get minutes
-	tmp.minutes = 0;
-	while (TM_RTC_CHARISNUM(*(str + i))) {
-		tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
-		i++;
-	}
-	i++;
-	
-	// Get seconds
-	tmp.seconds = 0;
-	while (TM_RTC_CHARISNUM(*(str + i))) {
-		tmp.seconds = tmp.seconds * 10 + TM_RTC_CHAR2NUM(*(str + i));
-		i++;
-	}
-	i++;
-	
-	// Return status from set date time function 
-	return TM_RTC_SetDateTime(&tmp);
-}
-
-
-//
-void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) 
-{
-    (void)format;
-	uint32_t unix = rtc_counter_get();
-
-    TM_RTC_GetDateTimeFromUnix(data, unix);
-}
-
-
-//
-uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data) 
-{
-	uint32_t days = 0, seconds = 0;
-	uint16_t i;
-	uint16_t year = (uint16_t)(data->year + 2000);
-
-	// Year is below offset year
-	if (year < TM_RTC_OFFSET_YEAR) {
-		return 0;
-	}
-	// Days in back years
-	for (i = TM_RTC_OFFSET_YEAR; i < year; i++) {
-		days += TM_RTC_DAYS_IN_YEAR(i);
-	}
-	// Days in current year
-	for (i = 1; i < data->month; i++) {
-		days += TM_RTC_Months[TM_RTC_LEAP_YEAR(year)][i - 1];
-	}
-	// Day starts with 1
-	days += data->date - 1;
-	seconds = days * TM_RTC_SECONDS_PER_DAY;
-	seconds += data->hours * TM_RTC_SECONDS_PER_HOUR;
-	seconds += data->minutes * TM_RTC_SECONDS_PER_MINUTE;
-	seconds += data->seconds;
-	
-	// seconds = days * 86400;
-	return seconds;
-}
-
-
-//
-void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix) 
-{
-	uint16_t year;
-	
-	// Store unix time to unix in struct
-	data->unix = unix;
-	// Get seconds from unix
-	data->seconds = unix % 60;
-	// Go to minutes
-	unix /= 60;
-	// Get minutes
-	data->minutes = unix % 60;
-	// Go to hours 
-	unix /= 60;
-	// Get hours
-	data->hours = unix % 24;
-	// Go to days
-	unix /= 24;
-	
-	// Get week day
-	// Monday is day one
-	data->day = (unix + 3) % 7 + 1;
-
-	// Get year
-	year = 1970;
-	while (1) {
-		if (TM_RTC_LEAP_YEAR(year)) {
-			if (unix >= 366) {
-				unix -= 366;
-			} else {
-				break;
-			}
-		} else if (unix >= 365) {
-			unix -= 365;
-		} else {
-			break;
-		}
-		year++;
-	}
-	// Get year in xx format
-	data->year = (uint8_t) (year - 2000);
-	// Get month
-	for (data->month = 0; data->month < 12; data->month++) {
-		if (TM_RTC_LEAP_YEAR(year) && unix >= (uint32_t)TM_RTC_Months[1][data->month]) {
-			unix -= TM_RTC_Months[1][data->month];
-		} else if (unix >= (uint32_t)TM_RTC_Months[0][data->month]) {
-			unix -= TM_RTC_Months[0][data->month];
-		} else {
-			break;
-		}
-	}
-	// Get month
-	// Month starts with 1
-	data->month++;
-	// Get date
-	// Date starts with 1
-	data->date = unix + 1;
-}
-
-
-//
-void TM_RTC_PrintTime(void)
-{
-    TM_RTC_t data;
-    
-    uint32_t unix = rtc_counter_get();
-    
-    TM_RTC_GetDateTimeFromUnix(&data, unix);
-	
-	printf("%02d.%02d.%02d %02d:%02d:%02d\r\n", data.date, data.month, data.year,
-			data.hours, data.minutes, data.seconds);
-
-}
-
-
-//
-uint32_t RTC_GetUnixTime(void)
-{
-    TM_RTC_t currentTime;
-  
-    TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
-    return TM_RTC_GetUnixTimeStamp(&currentTime);
-}
-
-
-#if 0
-//
-void sntp_config(void)
-{
-	sntp_setoperatingmode(SNTP_OPMODE_POLL);
-	sntp_setservername(0, sSettings.sSNTP.ip1);
-  	sntp_setservername(1, sSettings.sSNTP.ip2);
-
-  	sntp_init();
-}
-
-
-//
-void lwip_time_sinhro(uint32_t utime)
-{
-	printf("SNTP: sinhro hook: %u\n\r", utime);
-	utime += 3600*(int)sSettings.sSNTP.timeZone;
-    TM_RTC_SetDataTimeUnix(utime);
-}
-#endif
+#include "rtc.h"
+#include "lwip/apps/sntp.h"
+#include "settings_api.h"
+#include <string.h>
+
+
+//TM_RTC_t calendar;
+
+/* Days in a month */
+uint8_t TM_RTC_Months[2][12] = {
+	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},	/* Not leap year */
+	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}	/* Leap year */
+};
+
+// monthly correction data sheet
+const uint8_t table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
+
+// monmonth data table of common year
+const uint8_t mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+/* Internal RTC defines */
+#define TM_RTC_LEAP_YEAR(year) 			((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
+#define TM_RTC_DAYS_IN_YEAR(x)			TM_RTC_LEAP_YEAR(x) ? 366 : 365
+#define TM_RTC_OFFSET_YEAR				1970
+#define TM_RTC_SECONDS_PER_DAY			86400
+#define TM_RTC_SECONDS_PER_HOUR			3600
+#define TM_RTC_SECONDS_PER_MINUTE		60
+#define TM_RTC_BCD2BIN(x)				((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))
+#define TM_RTC_CHAR2NUM(x)				((x) - '0')
+#define TM_RTC_CHARISNUM(x)				((x) >= '0' && (x) <= '9')
+
+
+extern SemaphoreHandle_t flash_mutex;
+
+
+
+/**
+  * @brief  rtc peripheral initialization.
+  * @param  calendar
+  * @retval 0: rtc already init
+            1: rtc init
+  */
+uint8_t TM_RTC_Init(void)
+{
+    TM_RTC_t datatime;
+    
+    // enable pwc and bpr clocks
+    crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
+    
+    // enable the battery-powered domain write operations
+    pwc_battery_powered_domain_access(TRUE);
+    
+    // check if rtc is initialized 
+    if (bpr_data_read(BPR_DATA4) != 0x1234)
+    {
+        // reset battery-powered domain register
+        bpr_reset();
+        
+        // enable the lext osc
+        crm_clock_source_enable(CRM_CLOCK_SOURCE_LEXT, TRUE);
+        // wait lext is ready
+        while(crm_flag_get(CRM_LEXT_STABLE_FLAG) == RESET);
+        // select the rtc clock source
+        crm_rtc_clock_select(CRM_RTC_CLOCK_LEXT);
+        
+        // enable rtc clock
+        crm_rtc_clock_enable(TRUE);
+        
+        // wait for rtc registers update 
+        rtc_wait_update_finish();
+        
+        // wait for the register write to complete
+        rtc_wait_config_finish();
+        
+        // set rtc divider: set rtc period to 1sec 
+        rtc_divider_set(32767);
+        
+        // wait for the register write to complete
+        rtc_wait_config_finish();
+        
+        // set date and time
+        datatime.date    = 1;
+        datatime.day     = 1;
+        datatime.month   = 1;
+        datatime.year    = 0;
+        datatime.hours   = 0;
+        datatime.minutes = 0;
+        datatime.seconds = 0;
+        
+        TM_RTC_SetDateTime(&datatime);
+        
+        // writes data to bpr register 
+        bpr_data_write(BPR_DATA4, 0x1234);
+        
+        return 1;
+    }
+    else
+    {
+        // wait for rtc registers update
+        rtc_wait_update_finish();
+
+        // wait for the register write to complete
+        rtc_wait_config_finish();
+    
+        return 0;    
+    }
+}
+
+
+//
+void TM_RTC_SetDataTimeUnix(uint32_t unixTime)
+{
+    TM_RTC_t data;
+  
+    TM_RTC_GetDateTimeFromUnix(&data, unixTime);
+    rtc_counter_set(unixTime);
+    rtc_wait_config_finish();
+}
+
+
+/**
+  * @brief  set time. convert the input clock to a second.
+  *         the time basic : 1970.1.1
+  *         legitimate year: 1970 ~ 2099
+  * @param  calendar
+  * @retval 0: set time right.
+  *         1: set time failed.
+  */
+TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data)
+{
+    uint32_t seccount = 0;
+    
+    if (data->year > 99 || 
+		data->month == 0 || 
+		data->month > 12 ||
+		data->date == 0 ||
+		data->date > TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + data->year) ? 1 : 0][data->month - 1] ||
+		data->hours > 23 ||
+		data->minutes > 59 ||
+		data->seconds > 59 ||
+		data->day == 0 ||
+		data->day > 7) 
+    {
+		return TM_RTC_Result_Error; 
+	}
+    
+    // enable pwc and bpr clocks
+    crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
+    crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
+    
+    // enable write access to bpr domain
+    pwc_battery_powered_domain_access(TRUE);
+    
+    // set the rtc counter value
+    seccount = TM_RTC_GetUnixTimeStamp(data);
+    rtc_counter_set(seccount);
+    
+    // wait for the register write to complete
+    rtc_wait_config_finish();
+    
+    return TM_RTC_Result_Ok;
+}
+
+
+//
+TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str) 
+{
+	TM_RTC_t tmp;
+	uint8_t i = 0;
+	
+	// Get date
+	tmp.date = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	// Get month
+	tmp.month = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	// Get year
+	tmp.year = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	// Get day in a week
+	tmp.day = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.day = tmp.day * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	// Get hours
+	tmp.hours = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	// Get minutes
+	tmp.minutes = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	// Get seconds
+	tmp.seconds = 0;
+	while (TM_RTC_CHARISNUM(*(str + i))) {
+		tmp.seconds = tmp.seconds * 10 + TM_RTC_CHAR2NUM(*(str + i));
+		i++;
+	}
+	i++;
+	
+	// Return status from set date time function 
+	return TM_RTC_SetDateTime(&tmp);
+}
+
+
+//
+void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) 
+{
+    (void)format;
+	uint32_t unix = rtc_counter_get();
+
+    TM_RTC_GetDateTimeFromUnix(data, unix);
+}
+
+
+//
+uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data) 
+{
+	uint32_t days = 0, seconds = 0;
+	uint16_t i;
+	uint16_t year = (uint16_t)(data->year + 2000);
+
+	// Year is below offset year
+	if (year < TM_RTC_OFFSET_YEAR) {
+		return 0;
+	}
+	// Days in back years
+	for (i = TM_RTC_OFFSET_YEAR; i < year; i++) {
+		days += TM_RTC_DAYS_IN_YEAR(i);
+	}
+	// Days in current year
+	for (i = 1; i < data->month; i++) {
+		days += TM_RTC_Months[TM_RTC_LEAP_YEAR(year)][i - 1];
+	}
+	// Day starts with 1
+	days += data->date - 1;
+	seconds = days * TM_RTC_SECONDS_PER_DAY;
+	seconds += data->hours * TM_RTC_SECONDS_PER_HOUR;
+	seconds += data->minutes * TM_RTC_SECONDS_PER_MINUTE;
+	seconds += data->seconds;
+	
+	// seconds = days * 86400;
+	return seconds;
+}
+
+
+//
+void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix) 
+{
+	uint16_t year;
+	
+	// Store unix time to unix in struct
+	data->unix = unix;
+	// Get seconds from unix
+	data->seconds = unix % 60;
+	// Go to minutes
+	unix /= 60;
+	// Get minutes
+	data->minutes = unix % 60;
+	// Go to hours 
+	unix /= 60;
+	// Get hours
+	data->hours = unix % 24;
+	// Go to days
+	unix /= 24;
+	
+	// Get week day
+	// Monday is day one
+	data->day = (unix + 3) % 7 + 1;
+
+	// Get year
+	year = 1970;
+	while (1) {
+		if (TM_RTC_LEAP_YEAR(year)) {
+			if (unix >= 366) {
+				unix -= 366;
+			} else {
+				break;
+			}
+		} else if (unix >= 365) {
+			unix -= 365;
+		} else {
+			break;
+		}
+		year++;
+	}
+	// Get year in xx format
+	data->year = (uint8_t) (year - 2000);
+	// Get month
+	for (data->month = 0; data->month < 12; data->month++) {
+		if (TM_RTC_LEAP_YEAR(year) && unix >= (uint32_t)TM_RTC_Months[1][data->month]) {
+			unix -= TM_RTC_Months[1][data->month];
+		} else if (unix >= (uint32_t)TM_RTC_Months[0][data->month]) {
+			unix -= TM_RTC_Months[0][data->month];
+		} else {
+			break;
+		}
+	}
+	// Get month
+	// Month starts with 1
+	data->month++;
+	// Get date
+	// Date starts with 1
+	data->date = unix + 1;
+}
+
+
+//
+void TM_RTC_PrintTime(void)
+{
+    TM_RTC_t data;
+    
+    uint32_t unix = rtc_counter_get();
+    
+    TM_RTC_GetDateTimeFromUnix(&data, unix);
+	
+	printf("%02d.%02d.%02d %02d:%02d:%02d\r\n", data.date, data.month, data.year,
+			data.hours, data.minutes, data.seconds);
+
+}
+
+
+//
+uint32_t RTC_GetUnixTime(void)
+{
+    TM_RTC_t currentTime;
+  
+    TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
+    return TM_RTC_GetUnixTimeStamp(&currentTime);
+}
+

+ 35 - 2
fw/modules/terminal/terminal_sbs.cpp

@@ -5,6 +5,9 @@
 #include <string.h>
 #include <stdbool.h>
 
+extern "C" {
+    #include "log.h"
+}
 
 SbsTerminal sbsTerminal;
 Terminal* pTerminal; //Глобальный указатель на терминал
@@ -24,7 +27,7 @@ void SbsTerminal::configure()
     pTerminal = &sbsTerminal;
     
     m_dataQueue = xQueueCreate(20, 1);
-    xTaskCreate(vTerminal, "terminal", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);    
+    xTaskCreate(vTerminal, "terminal", 2*configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL);    
 }
 
 //
@@ -35,10 +38,40 @@ int SbsTerminal::execute(int argc, const char * const *argv)
     if (argc <= 0) {
         return -1;
     }
-    
     if (strcmp(argv[0], "help") == 0) {
         return help(argc, argv);
     }
+    if (strcmp(argv[0], "version") == 0) {
+        return version(argc, argv);
+    }
+    // ---------------------------------------------------------------------- //
+    // Archive API
+    
+    // Добавить N новых записей в архив
+    if (strcmp(argv[0], "add_aentry") == 0) {
+        if (argc > 1)
+            test_add_random_archive_entry(atoi(argv[1]));
+        else
+            printf("No record counter\r\n");
+        
+        return 0;
+    }
+    // Информация об архиве
+    if (strcmp(argv[0], "ainfo") == 0) {
+        test_archive_info();
+        return 0;
+    }
+    // Fetch archive entry
+    if (strcmp(argv[0], "afetch") == 0) {
+        test_fetch();
+        return 0;
+    }
+    // Format archive FS
+    if (strcmp(argv[0], "aformat") == 0) {
+        test_archive_format();
+        return 0;
+    }
+    
     // ---------------------------------------------------------------------- //
     else {
         printeol();

BIN
output/fw.bin


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 430 - 430
project/ewarm/iap/iap.dep


Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 676 - 708
project/ewarm/module_universal_io.dep


BIN
tools/__pycache__/modbus.cpython-310.pyc


+ 231 - 9
tools/io_module.py

@@ -4,8 +4,10 @@ from colorama import Fore
 import time
 import os
 
-reg_table = {'in_bits': 0x0100, 'in_cnt': 0x0102, 'in_mode': 0x0120,'uptime': 0x0800, 
-             'rtc_unix': 0x0802, 'rtc_sinhro': 0x0804}
+reg_table = {'in_bits': 0x0100, 'in_cnt': 0x0102, 'in_mode': 0x0120, 'in_norm': 0x0122, 'in_deb_start': 0x124,
+             'out_cur': 0x0200, 'out_mode': 0x0202, 'out_mode_save': 0x0203, 'pwm_duty': 0x0210,
+             'pwm_duty_save': 0x0220, 'pwm_per': 0x0230, 'pwm_per_save': 0x0240, 
+             'rtc_unix': 0x0802, 'rtc_sinhro': 0x0804, 'uptime': 0x0800,}
 
 
 class IO_Module(Modbus):
@@ -93,6 +95,115 @@ class IO_Module(Modbus):
     def set_inputs_mode(self, val):
         self.write_holding_register(reg_table['in_mode'], val)
 
+    #        
+    def set_input_mode(self, input, val):
+        ret = self.read_holding_registers(reg_table['in_mode'], 1)
+        if val == 1:
+            data = ret[0] | (0b1 << (input - 1))
+        else:
+            data = ret[0] & ~(0b1 << (input - 1))
+        self.set_inputs_mode(data)
+
+    # 0x0122 - нормальное состояние входов
+    def get_inputs_norm_state(self):
+        data = self.read_holding_registers(reg_table['in_norm'], 1)
+        return format(data[0], '08b')
+
+    def set_inputs_norm_state(self, val):
+        self.write_holding_register(reg_table['in_norm'], val)
+
+    # 0x0124 - время антидребезга (ms)
+    def get_debounce_channel(self, input):
+        data = self.read_holding_registers(reg_table['in_deb_start'] + input - 1, 1)
+        return data[0]
+
+    def get_debounce_channels(self):
+        return self.read_holding_registers(reg_table['in_deb_start'], 8)
+
+    def set_debounce_channel(self, input, val):
+        self.write_holding_register(reg_table['in_deb_start'] + input - 1, val)
+
+    # 0x0200 - текущее состояние выходов в обычно режиме
+    def get_outputs(self):
+        data = self.read_holding_registers(reg_table['out_cur'], 1)
+        return format(data[0], '08b')
+
+    # 0x0200 - текущее состояние выходов в обычно режиме
+    def set_outputs(self, val):
+        self.write_holding_register(reg_table['out_cur'], val)
+
+    def set_output(self, output, val):
+        ret = self.read_holding_registers(reg_table['out_cur'], 1)
+        if val == 1:
+            data = ret[0] | (0b1 << (output - 1))
+        else:
+            data = ret[0] & ~(0b1 << (output - 1))
+        self.set_outputs(data)
+
+    # 0x0202 - режим работы выходов; 0 - обычный, 1 - ШИМ
+    def get_outputs_mode(self):
+        data = self.read_holding_registers(reg_table['out_mode'], 1)
+        return format(data[0], '08b')
+    
+    def set_outputs_mode(self, val):
+        self.write_holding_register(reg_table['out_mode'], val)
+
+    def set_output_mode(self, output, val):
+        ret = self.read_holding_registers(reg_table['out_mode'], 1)
+        if val == 1:
+            data = ret[0] | (0b1 << (output - 1))
+        else:
+            data = ret[0] & ~(0b1 << (output - 1))
+        self.set_outputs_mode(data)
+
+    # 0x0203 - состояние выходов (режим обычного выхода) в безопасном режиме работы
+    def get_outputs_mode_save(self):
+        data = self.read_holding_registers(reg_table['out_mode_save'], 1)
+        return format(data[0], '08b')
+
+    def set_outputs_mode_save(self, val):
+        self.write_holding_register(reg_table['out_mode_save'], val)
+
+    def set_output_mode_save(self, output, val):
+        ret = self.read_holding_registers(reg_table['out_mode_save'], 1)
+        if val == 1:
+            data = ret[0] | (0b1 << (output - 1))
+        else:
+            data = ret[0] & ~(0b1 << (output - 1))
+        self.set_outputs_mode_save(data)
+
+    # 0x0210 - заполнение PWM (%)
+    def get_pwm_duty(self, output):
+        data = self.read_holding_registers(reg_table['pwm_duty'] + output - 1, 1)
+        return data[0]
+    
+    def get_pwm_duty_all(self):
+        return self.read_holding_registers(reg_table['pwm_duty'], 8)
+
+    def set_pwm_duty(self, output, val):
+        self.write_holding_register(reg_table['pwm_duty'] + output - 1, val)
+
+    # 0x0220 - заполнение PWM (%)
+    def get_pwm_duty_all_save(self):
+        return self.read_holding_registers(reg_table['pwm_duty_save'], 8)
+
+    def set_pwm_duty_save(self, output, val):
+        self.write_holding_register(reg_table['pwm_duty_save'] + output - 1, val)
+
+    # 0x0230 - период PWM (0.1 сек)
+    def get_pwm_period_all(self):
+        return self.read_holding_registers(reg_table['pwm_per'], 8)
+
+    def set_pwm_period(self, output, val):
+        self.write_holding_register(reg_table['pwm_per'] + output - 1, val)
+
+    # 0x0240 - период PWM в безопасном режиме (0.1 сек)
+    def get_pwm_period_all_save(self):
+        return self.read_holding_registers(reg_table['pwm_per_save'], 8)
+
+    def set_pwm_period_save(self, output, val):
+        self.write_holding_register(reg_table['pwm_per_save'] + output - 1, val)
+
     def get_uptime(self):
         return self.read_uint32_holding(reg_table['uptime'])
 
@@ -106,8 +217,9 @@ class IO_Module(Modbus):
 
 def main():
     colorama.init(autoreset=True)
-    dev = IO_Module('COM24', 115200, 1)
+    dev = IO_Module('COM24', 115200, 15)
     dev.MB_DEBUG = False
+    
     # dev.update('fw.bin')
 
     # Запрос системных параметров, установка времени
@@ -121,19 +233,129 @@ def main():
     # unix_time = dev.get_rtc()
     # print(f'RTC: {time.ctime(unix_time)}. Unix time stamp:  {unix_time}')
     
-    # while True:
-    for i in range(10):
+    
+    
+    for i in range(1, 9):
+        dev.set_input_mode(i, 1)
+        print('Inputs mode [bit field]   :', Fore.GREEN + dev.get_inputs_mode())
+
+    for i in range(1, 9):
+        dev.set_debounce_channel(i, 100 + i)
+        # dev.set_output(i, 1)
+        # dev.set_output_mode(i, 1)
+        
+    # 0x0203 - состояние выходов (режим обычного выхода) в безопасном режиме работы
+    # for i in range(1, 9):
+    #     dev.set_output_mode_save(i, 0)
+
+    # 0x0210 - заполнение PWM (ms)
+    # 0x0220 - заполнение PWM (%)
+    # 0x0230 - период PWM (0.1 сек)
+    # 0x0240 - период PWM в безопасном режиме (0.1 сек)
+    # for i in range(1, 9):
+    #     dev.set_pwm_duty(i, 10 + i)    
+    #     dev.set_pwm_duty_save(i, 20 + i)
+    #     dev.set_pwm_period(i, 10 + i)
+    #     dev.set_pwm_period_save(i, 20 + i)
+
+    # -----------------------------------------------------------------------------
+    # Тесты PWM
+    # Установить 1-ый выход в режим PWM
+    # for i in range(3, 9):    
+        # dev.set_output_mode(i, 0)
+    
+    # dev.set_output_mode(1, 1)
+    # dev.set_pwm_period(1, 30)
+
+    # dev.set_pwm_period(1, 50)
+    # dev.set_pwm_duty(2, 10)
+        
+    # return
+
+    # Установить нормальное состояние входов
+    # dev.set_inputs_norm_state(0b00110101)
+
+    # print(dev.get_pwm_duty_all())
+
+    while True:
         print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')
-        print('Inputs values [bit field :', Fore.GREEN + dev.get_inputs_bit())
-        print('Inputs mode [bit field]  :', Fore.GREEN + dev.get_inputs_mode())
+        # Значения входов (битовое поле)
+        print('Inputs values [bit field] :', Fore.GREEN + dev.get_inputs_bit())
+
+        # Режим работы входов (битовое поле)
+        print('Inputs mode [bit field]   :', Fore.GREEN + dev.get_inputs_mode())
+
+        # Нормальное состояние входов (битовое поле)
+        print('Inputs norm [bit field]   :', Fore.GREEN + dev.get_inputs_norm_state())
+
+        # Период антидребезга (ms)
+        print('Debounce input (ms)       :', Fore.GREEN + ' | '.join(str(el) for el in dev.get_debounce_channels()))
+
+        # Значение счетчиков
         data = dev.get_inputs_counters()
-        print('Inputs counters          :', Fore.GREEN + ' | '.join(str(el) for el in data))
-        dev.set_inputs_mode(i)
+        print('Inputs counters           :', Fore.GREEN + ' | '.join(str(el) for el in data))
+
+        # Текущее состояние выходов в обычном режиме
+        print('Outputs norm [bit field]  :', Fore.GREEN + dev.get_outputs())
+
+        # Состояние выходов в безопасном режиме
+        print('Outputs save [bit field]  :', Fore.GREEN + dev.get_outputs_mode_save())
+
+        # Режим работы выходов
+        print('Outputs mode [bit field]  :', Fore.GREEN + dev.get_outputs_mode())
+
+        # 0x0210 - заполнение PWM (ms)
+        print('PWM duty cycle [%]        :', Fore.GREEN + ' | '.join(str(el) for el in dev.get_pwm_duty_all()))
+
+        # 0x0220 - заполнение PWM в безопасном режиме (ms)
+        print('PWM duty cycle (save) [%] :', Fore.GREEN + ' | '.join(str(el) for el in dev.get_pwm_duty_all_save()))
+
+        # 0x0230 - период PWM (0.1 сек)
+        print('PWM period [0.1 sec]      :', Fore.GREEN + ' | '.join(str(el) for el in dev.get_pwm_period_all()))
+        
+        # 0x0240 - период PWM в безопасном режиме (0.1 сек)
+        print('PWM period save [0.1 sec] :', Fore.GREEN + ' | '.join(str(el) for el in dev.get_pwm_period_all_save()))
 
+        # Дергаем одним выходом        
+        # dev.set_output(2, trigger)
+        # trigger = not trigger
+
+        # # Для проверки выходов в обычном режиме
+        # for i in range(1, 9):
+        #     dev.set_output(i, 1)
+        #     print('Outputs norm [bit field]  :', Fore.GREEN + dev.get_output())
+        #     time.sleep(0.1)
+
+        # for i in range(1, 9):
+        #     dev.set_output(i, 0)
+        #     print('Outputs norm [bit field]  :', Fore.GREEN + dev.get_output())
+        #     time.sleep(0.1)
+
+        # # Режим работы выходов
+        # for i in range(1, 9):
+        #     dev.set_output_mode(i, 1)
+        #     print('Outputs mode [bit field]  :', Fore.GREEN + dev.get_outputs_mode())
+        #     time.sleep(0.1)
+
+        # for i in range(1, 9):
+        #     dev.set_output_mode(i, 0)
+        #     print('Outputs mode [bit field]  :', Fore.GREEN + dev.get_outputs_mode())
+        #     time.sleep(0.1)
+
+        # break
         time.sleep(1)
 
+
+
+    # for i in range(1, 9):
+    #     dev.set_input_mode(i, 1)
+    #     print('Inputs mode [bit field]  :', Fore.GREEN + dev.get_inputs_mode())
     
 
+    # for i in range(8, 0, -1):
+    #     dev.set_input_mode(i, 0)
+    #     print('Inputs mode [bit field]  :', Fore.GREEN + dev.get_inputs_mode())
+        
 
 if __name__ == '__main__':
     main()

+ 1 - 1
tools/modbus.py

@@ -99,7 +99,7 @@ class Modbus(ModbusMixin):
         crc_received = response[-2:]
         crc_calculated = self._crc(response[:-2])
         if crc_received != crc_calculated:
-            raise ChecksumError("CRC check dailed (got: 0x{}, calculated: 0x{})".format(
+            raise ChecksumError("CRC check failed (got: 0x{}, calculated: 0x{})".format(
                 b2a_hex(crc_received).decode().upper(), b2a_hex(crc_calculated).decode().upper()))
         return response
 

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä