WIZnet S2E Configuration Module Ver 1.0
With the WIZnet Configuration Module, users can easily perform configuration tasks such as network settings and device management without the need for a configu
SOLOMON SYSTECH - Monochrome 0.96" 128x64 OLED Graphic Display
x 1
Software Apps and online services
WIZnet S2E Configuration Module: A New Solution for Resolving Network Configuration Issues in Industrial SitesProduct Features and Benefits
In industrial environments, network configuration and management can be complex and time-consuming tasks. Users often struggle with the complex setup processes and interfaces of S2E modules. To alleviate this discomfort, we have developed a new solution utilizing WIZnet's W7500 MCU, the WIZnet S2E Configuration Module.
Product Features and Benefits
he WIZnet S2E Configuration Module is compatible with the WIZ750SR-100 series and assists users in easily and intuitively performing configuration tasks such as network settings and device management. By connecting the SSD1306 display, it provides menus and necessary information to users, simplifying setting changes and management.
This module was tested with the Surf5 board and has successfully implemented seamless communication with the WIZ750SR series, along with basic configuration changes and management functions. Through stable network connections and excellent performance, developers can manage and optimize network-based projects and applications more efficiently.
Feature Overview
- OLED Display Menus and Functions: Users can easily access various functions such as information display, IP settings, channel settings, UART settings, and reset.
- Development Convenience: Through GPIO ports, various hardware components (e.g., rotary encoder, tactile switch) can be connected to create a user interface.
Application Fields and Expected Effects
The WIZnet S2E Configuration Module is suitable for various industrial fields and applications where network communication is essential. Users can more easily adjust network settings and efficiently manage devices with this module, thereby improving work efficiency and saving time and costs.
We are confident that the WIZnet S2E Configuration Module will innovatively change network management in industrial sites. Visit our website now to learn more about this innovative solution. Your network management will become much more straightforward.
WIZnet S2E Configuration Module: Test and Development Specifications Summary
Test Development Board:
- Model: Surf 5
- MCU: W7500
Development Module:
- Display: SSD 1306 128x64
- Input Devices: Rotary Encoder, Tactile Switch
GPIO Configuration:
- Tactile Switch: PB09
- Rotary Encoder Button: PA10
- Rotary Encoder Clock: PC02
- Rotary Encoder DT: PC03
- OLED SCL (Serial Clock Line): PA05
- OLED SDA (Serial Data Line): PA06
Based on these specifications, the testing and development of the WIZnet S2E Configuration Module were conducted. Users can refer to this information to configure and utilize the module according to their project needs.
Simple Module Schematic:
Rotary Encoder Button: PA10 and Rotary Encoder Clock: PC02 have 0.47uF capacitors connected to the ground to eliminate bouncing. The Rotary Encoder Button: PA10, due to the characteristics of the rotary encoder being active low, is connected with a pull-up resistor and a 0.47uF capacitor for debounce purposes. The Tactile Switch: PB09, being active high, is connected with a pull-down resistor.
Module Photo:
Code:
<main.c>
The reason for implementing the logic in this main function is to execute the existing operations of the S2E module when the OLED is not used, and to selectively use the logic of the Config module only when it is used. It represents the logic of the main function that checks the initialization status of the OLED display and performs different operations depending on the connection status. When the program starts, it first initializes the OLED display and sets it to a 'connected' state if the initialization is successful. Then, within the infinite loop, if the OLED is in a 'connected' state, it proceeds with button operations and display updates, and if an error occurs during the update, it switches to an 'unlinked' state.
#include "configmoduleHandler.h"
#include "ssd1306.h"
#include "W7500x_it.h"
...
/* Private function prototypes -----------------------------------------------*/
void GPIO_InitializeInterrupt(void);
/* Private variables ---------------------------------------------------------*/
I2C_ConfigStruct conf;
volatile uint8_t SSD1306_Link_Check_flag = SSD1306_UNLINKED;
int main(void)
{
conf.scl = I2C_PA_5;
conf.sda = I2C_PA_6;
...
...
// init ssd1306
if(SSD1306_Init (&conf, SSD1306_ADDR) == SSD1306_SUCCESS){
SSD1306_Link_Check_flag = SSD1306_LINKED;
}
while(1) // main loop
{
// init ssd1306 & Link status check
if (SSD1306_Link_Check_flag == SSD1306_LINKED) { //SSD1306 linked
// update
Config_Module_Btn_Process();
SSD1306_PRINT_DATA_PROCESS();
if(SSD1306_UpdateScreen (&conf, SSD1306_ADDR) == SSD1306_ERROR){ //link status check
SSD1306_Link_Check_flag = SSD1306_UNLINKED;
}
}
else if (SSD1306_Link_Check_flag == SSD1306_UNLINKED){
do_segcp();
delay_cnt++;
if(delay_cnt >= 100000){ //SSD1306 Unlinked //SSD1306 Unlinked
if(SSD1306_Init (&conf, SSD1306_ADDR) == SSD1306_SUCCESS){ //link status check
SSD1306_Link_Check_flag = SSD1306_LINKED;
}
delay_cnt = 0;
}
}
...
...
}
}
...
<w7500x_it.c>
The rotary encoder button, tactile switch, rotary encoder clock, and rotary encoder DT are assigned to PA10, PB09, PC02, and PC03, respectively. In the w7500, a total of four interrupt handlers are assigned from A to D, respectively. Enum is used to store the status of the button, and button data is saved in a variable through each interrupt. When a signal enters each port, an interrupt occurs, and the status of the button is stored in the variable.
/* Private variables ---------------------------------------------------------*/
uint8_t btn_rotary_encoder = 0;
uint8_t btn_ok_back = 0;
__weak void PORT0_Handler(void)
{
if(!GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_10)){
btn_rotary_encoder = OK;
}
printf("OK \r\n");
GPIO_INT_Clear(GPIOA);
}
__weak void PORT1_Handler(void)
{
if(GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)){
btn_rotary_encoder = BACK;
}
printf("BACK\r\n");
GPIO_INT_Clear(GPIOB);
}
/**
* @brief This function handles PORT2 Handler.
* @param None
* @retval None
*/
;
__weak void PORT2_Handler(void)
{
uint8_t clk_state = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_2);
uint8_t dt_state = GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_3);
if(clk_state == SET){
if(dt_state){
btn_rotary_encoder = RIGHT;
}
else{
btn_rotary_encoder = LEFT;
}
}
GPIO_INT_Clear(GPIOC);
}
<w7500x_it.h>
//added code on w750sr basic code
typedef enum{
LEFT = 1,
RIGHT = 2,
OK = 3,
BACK = 4
}button;
extern uint8_t btn_rotary_encoder;
<configmoduleHandler.c>
#include "configmoduleHandler.h"
volatile int8_t current_page = 0; //Current Print Page
volatile int8_t current_cursor = 0; //Current Print Cursor
volatile int8_t ssd1306_page_num = PAGE_FIRST; //Current Entered Page
volatile int8_t ssd1306_line_num = 0; //Current Entered Line
volatile int8_t ssd1306_print_channel = 0; //Current Entered Ch
volatile int8_t draw_line_status = OFF; //Line On/Off Flag
volatile int8_t config_status = IS_WAITING_FOR_CONFIG; //Current Configuration Status
volatile int8_t config_index_cnt = 0; // Count Variable for Config Array Index
volatile uint8_t blink_delay_cnt = 0;
uint32_t prev_temp_config_data[16];
uint32_t temp_config_data[16];
char blink_config_data[16][10];
char strings[][MAX_STRING_LENGTH] = {"\0", "\0", "\0", "\0"};
const char str_top_menu[6][MAX_STRING_LENGTH] = {
"1. Device Info",
"2. Network Config",
"3. Ch Setting",
"4. Serial Port",
"5. RESET",
"6. add function"
};
const char str_device_info[4][MAX_STRING_LENGTH] = {
"Ver:",
"Name:",
"Code:",
"MC:"
};
const char str_network_config[2][MAX_STRING_LENGTH] = { //Network config
"1. DHCP",
"2. Static IP"
};
const char str_ip_config[4][MAX_STRING_LENGTH] = { //DHCP setting of Network config
"IP:",
"GW:",
"SN:",
"DNS:"
};
const char str_ch_config[4][MAX_STRING_LENGTH] = { //DHCP setting of Network config
"OP MODE:",
"Local Port:",
"RM IP:",
"RM PORT:"
};
const char str_serial_config[5][MAX_STRING_LENGTH] = {
"BaudRate:",
"data bit:",
"parity:",
"stop bit:",
"flow ctrl:"
};
const char str_empty_function[2][MAX_STRING_LENGTH] = {
"add function",
"add function"
};
above is code where functions related to the config module are stored. Before writing functions at the top of the code file, arrays and variables, and header files to be used are declared.
void Config_Module_Btn_Process(void){
uint32_t baud_tbl[] = {300, 600, 1200, 1800, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800};
DevConfig *dev_config = get_DevConfig_pointer();
int i = 0;
switch (btn_rotary_encoder)
{
case RIGHT: //Down scroll
switch (ssd1306_print_channel)
{
case SSD1306_PRINT_CH_0: //Main Page Function Selection Cursor Down
Ctrl_Decrease_Line(2, 1);
break;
case SSD1306_PRINT_CH_1:
switch (ssd1306_page_num)
{
case PAGE_FIRST:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Device Information Page Cursor Down
Ctrl_Decrease_Line(1, 0);
break;
case LINE_SECOND: //DHCP & STATIC IP Setting Cursor Down
Ctrl_Decrease_Line(1, 0);
break;
case LINE_THIRD: //Ch Settings
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Setting Elements Seletion Cursor Down
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
config_index_cnt--;
if(config_index_cnt < 0) config_index_cnt = 0;
break;
case CONFIG_IN_PROGRESS: //A Data of Ch Setting Elements Decrease
temp_config_data[config_index_cnt]--;
break;
default:
break;
}
break;
default:
break;
}
break;
case PAGE_SECOND:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Serial Port(UART)
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Serial Port(UART) Elements Seletion Cursor Down
if(config_index_cnt == 0){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", baud_tbl[temp_config_data[config_index_cnt]]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
config_index_cnt--;
if(config_index_cnt < 0) config_index_cnt = 0;
break;
case CONFIG_IN_PROGRESS: //A Data of Serial Port(UART) Elements Decrease
temp_config_data[config_index_cnt]--;
if(config_index_cnt == 0){
if(temp_config_data[config_index_cnt] > baud_460800) temp_config_data[config_index_cnt] = baud_460800;
}
else if(config_index_cnt == 1){
if(temp_config_data[config_index_cnt] >= 1) temp_config_data[config_index_cnt] = 1;
}
else if(config_index_cnt == 2){
if(temp_config_data[config_index_cnt] > parity_even) temp_config_data[config_index_cnt] = parity_even;
}
else if(config_index_cnt == 3){
if(temp_config_data[config_index_cnt] > stop_bit2) temp_config_data[config_index_cnt] = stop_bit2;
}
else if(config_index_cnt == 4){
if(temp_config_data[config_index_cnt] > flow_reverserts) temp_config_data[config_index_cnt] = flow_reverserts;
}
break;
default:
break;
}
break;
case LINE_SECOND:
//ADD FUNCTION
Ctrl_Decrease_Line(1, 0); //OK ? BACK?
break;
case LINE_THIRD:
//ADD FUNCTION
break;
default:
break;
}
break;
default:
break;
}
break;
case SSD1306_PRINT_CH_2:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Dhcp OK & BACK Selection
Ctrl_Decrease_Line(1, 0); //OK ? BACK?
break;
case LINE_SECOND: //STATIC Setting
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Static Elements Seletion Cursor Down
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
config_index_cnt--;
if(config_index_cnt < 0) config_index_cnt = 0;
break;
case CONFIG_IN_PROGRESS: //A Data of Static Elements Decrease
temp_config_data[config_index_cnt]--;
if(temp_config_data[config_index_cnt] > 255) temp_config_data[config_index_cnt] = 255;
break;
default:
break;
}
break;
default:
break;
}
break;
default:
break;
}
break;
case LEFT: //Up scroll
switch (ssd1306_print_channel)
{
case SSD1306_PRINT_CH_0: //Main Page Function Selection Cursor Up
Ctrl_Increase_Line(2, 1);
break;
case SSD1306_PRINT_CH_1:
switch (ssd1306_page_num)
{
case PAGE_FIRST:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Device Information Page Cursor Up
Ctrl_Increase_Line(1, 0);
break;
case LINE_SECOND: //DHCP & STATIC IP Setting Cursor Up
Ctrl_Increase_Line(1, 0);
break;
case LINE_THIRD: //Ch Settings
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Setting Element Seletion Cursor Up
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
config_index_cnt++;
if(config_index_cnt >= 7) config_index_cnt = 6;
break;
case CONFIG_IN_PROGRESS: //A Data of Ch Setting Elements Increase
temp_config_data[config_index_cnt]++;
break;
default:
break;
}
break;
default:
break;
}
break;
case PAGE_SECOND:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Serial Port(UART)
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Serial Port(UART) Elements Seletion Cursor Up
if(config_index_cnt == 0){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", baud_tbl[temp_config_data[config_index_cnt]]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
config_index_cnt++;
if(config_index_cnt >= 5) config_index_cnt = 4;
break;
case CONFIG_IN_PROGRESS: //A Data of Serial Port(UART) Elements Increase
temp_config_data[config_index_cnt]++;
if(config_index_cnt == 0){
if(temp_config_data[config_index_cnt] > baud_460800) temp_config_data[config_index_cnt] = baud_300;
}
else if(config_index_cnt == 1){
if(temp_config_data[config_index_cnt] >= 1) temp_config_data[config_index_cnt] = 0;
}
else if(config_index_cnt == 2){
if(temp_config_data[config_index_cnt] > parity_even) temp_config_data[config_index_cnt] = parity_none;
}
else if(config_index_cnt == 3){
if(temp_config_data[config_index_cnt] > stop_bit2) temp_config_data[config_index_cnt] = stop_bit1;
}
else if(config_index_cnt == 4){
if(temp_config_data[config_index_cnt] > flow_reverserts) temp_config_data[config_index_cnt] = flow_none;
}
break;
default:
break;
}
break;
case LINE_SECOND:
Ctrl_Increase_Line(1, 0); //OK ? BACK?
break;
case LINE_THIRD:
//ADD FUNCTION
break;
default:
break;
}
break;
default:
break;
}
break;
case SSD1306_PRINT_CH_2:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Dhcp OK & BACK Selection
Ctrl_Increase_Line(1, 0); //OK ? BACK?
break;
case LINE_SECOND: //STATIC Setting
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Static Elements Seletion Cursor Up
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
config_index_cnt++;
if(config_index_cnt >= 16) config_index_cnt = 15;
break;
case CONFIG_IN_PROGRESS: //A Data of Static Elements Increase
temp_config_data[config_index_cnt]++;
if(temp_config_data[config_index_cnt] > 255) temp_config_data[config_index_cnt] = 0;
break;
default:
break;
}
break;
default:
break;
}
break;
default:
break;
}
break;
case OK: //OK BUTTON(Enter & Determine)
switch (ssd1306_print_channel)
{
case SSD1306_PRINT_CH_0: //Main Page, Enter One of Functions
ssd1306_print_channel = SSD1306_PRINT_CH_1;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
current_page = PAGE_FIRST;
current_cursor = LINE_FIRST;
break;
case SSD1306_PRINT_CH_1:
switch (ssd1306_page_num)
{
case PAGE_FIRST:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Device Information Page Back
ssd1306_print_channel = SSD1306_PRINT_CH_0;
break;
case LINE_SECOND: //Determine DHCP & STATIC IP Setting
ssd1306_print_channel = SSD1306_PRINT_CH_2;
ssd1306_line_num = current_cursor;
break;
case LINE_THIRD: //Enter Ch Settings
current_page = PAGE_FIRST;
current_cursor = LINE_THIRD;
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Determine Setting Element
blink_delay_cnt = 0;
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
config_status = CONFIG_IN_PROGRESS;
break;
case CONFIG_IN_PROGRESS: //Determine Current Data of Ch Setting Elements & Back to previous state for other Setting Elements Seletion
config_status = CONFIG_DATA_SELECTION;
break;
default:
config_status = IS_WAITING_FOR_CONFIG;
break;
}
break;
default:
break;
}
break;
case PAGE_SECOND:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Serial Port(UART)
current_page = PAGE_SECOND;
current_cursor = LINE_FIRST;
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Determine Setting Element
blink_delay_cnt = 0;
if(config_index_cnt == 0){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", baud_tbl[temp_config_data[config_index_cnt]]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
config_status = CONFIG_IN_PROGRESS;
break;
case CONFIG_IN_PROGRESS: //Determine Current Data of Serial Port(UART) Elements & Back to previous state for other Setting Elements Seletion
config_status--;
break;
default:
config_status = IS_WAITING_FOR_CONFIG;
break;
}
break;
case LINE_SECOND: //RESET
if(current_cursor == 0){ //RESET OK
device_reboot();
ssd1306_print_channel = SSD1306_PRINT_CH_0;
current_page = PAGE_SECOND;
current_cursor = LINE_SECOND;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
}
else{ //RESET Back
ssd1306_print_channel = SSD1306_PRINT_CH_0;
current_page = PAGE_SECOND;
current_cursor = LINE_SECOND;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
}
break;
case LINE_THIRD: //Add Function
ssd1306_print_channel = SSD1306_PRINT_CH_0;
current_page = PAGE_SECOND;
current_cursor = LINE_THIRD;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
break;
default:
break;
}
break;
default:
break;
}
break;
case SSD1306_PRINT_CH_2:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Enter Dhcp OK & BACK Selection
if(current_cursor == 0){ //DHCP OK
dev_config->options.dhcp_use = 1;
process_dhcp();
flash_update_start();
save_DevConfig_to_storage();
flash_update_end();
device_reboot();
ssd1306_print_channel--;
current_page = PAGE_FIRST;
current_cursor = LINE_SECOND;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
}
else{ //DHCP Back
ssd1306_print_channel--;
current_page = PAGE_FIRST;
current_cursor = LINE_SECOND;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
}
blink_delay_cnt = 0;
break;
case LINE_SECOND: //Enter STATIC Setting
current_page = PAGE_FIRST;
current_cursor = LINE_SECOND;
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Determine Setting Element
blink_delay_cnt = 0;
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
config_status = CONFIG_IN_PROGRESS;
break;
case CONFIG_IN_PROGRESS: //Determine Current Data of Static Elements & Back to previous state for other Setting Elements Seletion
config_status--;
break;
default:
config_status = IS_WAITING_FOR_CONFIG;
break;
}
break;
default:
break;
}
break;
default:
break;
}
break;
case BACK: //BACK BUTTON
switch (ssd1306_print_channel)
{
case SSD1306_PRINT_CH_0: //Main Page, Doing Notting
break;
case SSD1306_PRINT_CH_1:
switch (ssd1306_page_num)
{
case PAGE_FIRST:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Device Information Page Back
ssd1306_print_channel--;
current_page = PAGE_FIRST;
current_cursor = LINE_FIRST;
break;
case LINE_SECOND: //Back on DHCP & STATIC IP Setting
ssd1306_print_channel--;
current_page = PAGE_FIRST;
current_cursor = LINE_SECOND;
break;
case LINE_THIRD: //Back on Ch Settings
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Back on Ch Settings
if(set_flag_on_data_change(prev_temp_config_data, temp_config_data, 7)){ //Before Back, Detect Changed Data
dev_config->network_info[0].working_mode = temp_config_data[0];
dev_config->network_info[0].local_port = temp_config_data[1];
dev_config->network_info[0].remote_ip[0] = temp_config_data[2];
dev_config->network_info[0].remote_ip[1] = temp_config_data[3];
dev_config->network_info[0].remote_ip[2] = temp_config_data[4];
dev_config->network_info[0].remote_ip[3] = temp_config_data[5];
dev_config->network_info[0].remote_port = temp_config_data[6];
flash_update_start();
save_DevConfig_to_storage();
flash_update_end();
device_reboot();
}
ssd1306_print_channel--;
blink_delay_cnt = 0;
current_page = PAGE_FIRST;
current_cursor = LINE_THIRD;
config_index_cnt = 0;
config_status = IS_WAITING_FOR_CONFIG;
break;
case CONFIG_IN_PROGRESS: //Cancel Changed Data
for(i = 0; i < 7; i++){
temp_config_data[i] = prev_temp_config_data[i];
}
config_status = CONFIG_DATA_SELECTION;
break;
default:
config_status = IS_WAITING_FOR_CONFIG;
break;
}
break;
default:
break;
}
break;
case PAGE_SECOND:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Serial Port(UART)
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Back on Setting
if(set_flag_on_data_change(prev_temp_config_data, temp_config_data, 5)){ //Before Back, Detect Changed Data
dev_config->serial_info[0].baud_rate = temp_config_data[0];
dev_config->serial_info[0].data_bits = temp_config_data[1];
dev_config->serial_info[0].parity = temp_config_data[2];
dev_config->serial_info[0].stop_bits = temp_config_data[3];
dev_config->serial_info[0].flow_control = temp_config_data[4];
flash_update_start();
save_DevConfig_to_storage();
flash_update_end();
device_reboot();
printf("\r\n change \r\n");
}
ssd1306_print_channel--;
blink_delay_cnt = 0;
current_page = PAGE_SECOND;
current_cursor = LINE_FIRST;
config_index_cnt = 0;
config_status = IS_WAITING_FOR_CONFIG;
break;
case CONFIG_IN_PROGRESS: //Cancel Changed Data
for(i = 0; i < 5; i++){
temp_config_data[i] = prev_temp_config_data[i];
}
config_status = CONFIG_DATA_SELECTION;
break;
default:
config_status = IS_WAITING_FOR_CONFIG;
break;
}
break;
case LINE_SECOND: //ADD FUNCTION
ssd1306_print_channel = SSD1306_PRINT_CH_0;
current_page = PAGE_SECOND;
current_cursor = LINE_SECOND;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
break;
case LINE_THIRD: //ADD FUNCTION
current_page = PAGE_SECOND;
current_cursor = LINE_THIRD;
break;
default:
break;
}
break;
default:
break;
}
break;
case SSD1306_PRINT_CH_2:
switch (ssd1306_line_num)
{
case LINE_FIRST: //Back on Dhcp OK & BACK Selection
blink_delay_cnt = 0;
ssd1306_print_channel--;
current_page = PAGE_FIRST;
current_cursor = LINE_SECOND;
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
break;
case LINE_SECOND: //Back on STATIC Setting
switch (config_status)
{
case CONFIG_DATA_SELECTION: //Back on Setting
if(set_flag_on_data_change(prev_temp_config_data, temp_config_data, 16)){ //Before Back, Detect Changed Data
dev_config->options.dhcp_use = 0;
dev_config->network_info_common.local_ip[0] = temp_config_data[0];
dev_config->network_info_common.local_ip[1] = temp_config_data[1];
dev_config->network_info_common.local_ip[2] = temp_config_data[2];
dev_config->network_info_common.local_ip[3] = temp_config_data[3];
dev_config->network_info_common.gateway[0] = temp_config_data[4];
dev_config->network_info_common.gateway[1] = temp_config_data[5];
dev_config->network_info_common.gateway[2] = temp_config_data[6];
dev_config->network_info_common.gateway[3] = temp_config_data[7];
dev_config->network_info_common.subnet[0] = temp_config_data[8];
dev_config->network_info_common.subnet[1] = temp_config_data[9];
dev_config->network_info_common.subnet[2] = temp_config_data[10];
dev_config->network_info_common.subnet[3] = temp_config_data[11];
dev_config->options.dns_server_ip[0] = temp_config_data[12];
dev_config->options.dns_server_ip[1] = temp_config_data[13];
dev_config->options.dns_server_ip[2] = temp_config_data[14];
dev_config->options.dns_server_ip[3] = temp_config_data[15];
flash_update_start();
save_DevConfig_to_storage();
flash_update_end();
device_reboot();
}
ssd1306_print_channel--;
blink_delay_cnt = 0;
current_page = PAGE_FIRST;
current_cursor = LINE_SECOND;
config_index_cnt = 0;
config_status = IS_WAITING_FOR_CONFIG;
break;
case CONFIG_IN_PROGRESS: //Cancel Changed Data
for(i = 0; i < 16; i++){
temp_config_data[i] = prev_temp_config_data[i];
}
config_status = CONFIG_DATA_SELECTION;
break;
default:
config_status = IS_WAITING_FOR_CONFIG;
break;
}
break;
default:
break;
}
break;
default:
break;
}
ssd1306_page_num = current_page;
ssd1306_line_num = current_cursor;
break;
default:
break;
}
btn_rotary_encoder = 0; //BTN Init
}
The above Config_Module_Btn_Process function decides which display screen to output using a button. This function receives the button status from the interrupt and stores the status value of the channel entered through the switch statement. The state of the button is stored in a variable when an interrupt occurs as the signal enters each port
void SSD1306_PRINT_DATA_PROCESS(void){
uint32_t baud_tbl[] = {300, 600, 1200, 1800, 2400, 4800, 9600, 14400, 19200, 28800, 38400, 57600, 115200, 230400, 460800};
char strings[][MAX_STRING_LENGTH] = {"\0", "\0", "\0", "\0"};
int i = 0;
DevConfig *dev_config = get_DevConfig_pointer();
switch (ssd1306_print_channel)
{
case SSD1306_PRINT_CH_0:
draw_line_status = DRAW_LINE_ON;
switch (current_page)
{
case PAGE_FIRST:
copyStringsRange(str_top_menu, strings, 0, 2);
break;
case PAGE_SECOND:
copyStringsRange(str_top_menu, strings, 3, 5);
break;
default:
break;
}
break;
case SSD1306_PRINT_CH_1:
switch (ssd1306_page_num)
{
case PAGE_FIRST:
switch (ssd1306_line_num)
{
case LINE_FIRST:
draw_line_status = DRAW_LINE_OFF;
if(current_cursor == LINE_FIRST){
snprintf(strings[0], sizeof(strings[0]), "%s%d.%d.%d %s", str_device_info[0], dev_config->fw_ver[0], dev_config->fw_ver[1], dev_config->fw_ver[2], STR_VERSION_STATUS);
snprintf(strings[1], sizeof(strings[1]), "%s%s", str_device_info[1],dev_config->module_name);
snprintf(strings[2], sizeof(strings[2]), "%s%d.%d.%d", str_device_info[2],dev_config->module_type[0],dev_config->module_type[1],dev_config->module_type[2]);
snprintf(strings[3], sizeof(strings[3]), "%s%02X:%02X:%02X:%02X:%02X:%02X", str_device_info[3], dev_config->network_info_common.mac[0],dev_config->network_info_common.mac[1],
dev_config->network_info_common.mac[2],dev_config->network_info_common.mac[3],dev_config->network_info_common.mac[4],dev_config->network_info_common.mac[5]);
}
else if(current_cursor == LINE_SECOND){
snprintf(strings[0], sizeof(strings[0]),"%s%d.%d.%d.%d", str_ip_config[0],dev_config->network_info_common.local_ip[0], dev_config->network_info_common.local_ip[1],
dev_config->network_info_common.local_ip[2], dev_config->network_info_common.local_ip[3]);
snprintf(strings[1], sizeof(strings[1]),"%s%d.%d.%d.%d", str_ip_config[1], dev_config->network_info_common.gateway[0], dev_config->network_info_common.gateway[1],
dev_config->network_info_common.gateway[2], dev_config->network_info_common.gateway[3]);
snprintf(strings[2], sizeof(strings[2]),"%s%d.%d.%d.%d", str_ip_config[2], dev_config->network_info_common.subnet[0], dev_config->network_info_common.subnet[1],
dev_config->network_info_common.subnet[2], dev_config->network_info_common.subnet[3]);
snprintf(strings[3], sizeof(strings[3]),"%s%d.%d.%d.%d", str_ip_config[3], dev_config->options.dns_server_ip[0], dev_config->options.dns_server_ip[1],
dev_config->options.dns_server_ip[2], dev_config->options.dns_server_ip[3]);
}
break;
case LINE_SECOND:
draw_line_status = DRAW_LINE_ON;
copyStringsRange(str_network_config, strings, 0, 1);
break;
case LINE_THIRD:
draw_line_status = DRAW_LINE_OFF;
switch (config_status)
{
case IS_WAITING_FOR_CONFIG:
temp_config_data[0] = dev_config->network_info[0].working_mode;
temp_config_data[1] = dev_config->network_info[0].local_port;
temp_config_data[2] = dev_config->network_info[0].remote_ip[0];
temp_config_data[3] = dev_config->network_info[0].remote_ip[1];
temp_config_data[4] = dev_config->network_info[0].remote_ip[2];
temp_config_data[5] = dev_config->network_info[0].remote_ip[3];
temp_config_data[6] = dev_config->network_info[0].remote_port;
for(i = 0; i < 7; i++){
snprintf(blink_config_data[i], sizeof(blink_config_data[i]), "%d", temp_config_data[i]);
prev_temp_config_data[i] = temp_config_data[i];
}
config_status = CONFIG_DATA_SELECTION;
break;
case CONFIG_DATA_SELECTION:
blink_delay_cnt++;
if(blink_delay_cnt <= 6){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%c%c", 32,32);
if(blink_delay_cnt == 12) blink_delay_cnt = 0;
}
break;
case CONFIG_IN_PROGRESS:
blink_delay_cnt++;
if(blink_delay_cnt <= 1){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%c%c", 32,32);
if(blink_delay_cnt == 2) blink_delay_cnt = 0;
}
break;
default:
break;
}
snprintf(strings[0], sizeof(strings[0]), "%s%s", str_ch_config[0],blink_config_data[0]);
snprintf(strings[1], sizeof(strings[1]), "%s%s", str_ch_config[1],blink_config_data[1]);
snprintf(strings[2], sizeof(strings[2]), "%s%s.%s.%s.%s", str_ch_config[2],blink_config_data[2], blink_config_data[3], blink_config_data[4], blink_config_data[5]);
snprintf(strings[3], sizeof(strings[3]), "%s%s", str_ch_config[3],blink_config_data[6]);
break;
default:
break;
}
break;
case PAGE_SECOND:
draw_line_status = DRAW_LINE_OFF;
switch (ssd1306_line_num)
{
case LINE_FIRST:
draw_line_status = DRAW_LINE_OFF;
switch (config_status)
{
case IS_WAITING_FOR_CONFIG:
temp_config_data[0] = dev_config->serial_info[0].baud_rate;
temp_config_data[1] = dev_config->serial_info[0].data_bits;
temp_config_data[2] = dev_config->serial_info[0].parity;
temp_config_data[3] = dev_config->serial_info[0].stop_bits;
temp_config_data[4] = dev_config->serial_info[0].flow_control;
for(i = 0; i < 5; i++){
if(i == 0){
snprintf(blink_config_data[i], sizeof(blink_config_data[i]), "%d", baud_tbl[temp_config_data[i]]);
}
else{
snprintf(blink_config_data[i], sizeof(blink_config_data[i]), "%d", temp_config_data[i]);
}
prev_temp_config_data[i] = temp_config_data[i];
}
config_status = CONFIG_DATA_SELECTION;
break;
case CONFIG_DATA_SELECTION:
blink_delay_cnt++;
if(blink_delay_cnt <= 6){
if(config_index_cnt == 0){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", baud_tbl[temp_config_data[config_index_cnt]]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%c%c", 32,32);
if(blink_delay_cnt == 12) blink_delay_cnt = 0;
}
break;
case CONFIG_IN_PROGRESS:
blink_delay_cnt++;
if(blink_delay_cnt <= 1){
if(config_index_cnt == 0){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", baud_tbl[temp_config_data[config_index_cnt]]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%c%c", 32,32);
if(blink_delay_cnt == 2) blink_delay_cnt = 0;
}
break;
default:
break;
}
if(config_index_cnt == 4){
snprintf(strings[0], sizeof(strings[0]), "%s%s", str_serial_config[4],blink_config_data[4]);
}
else{
for(i = 0; i < 4; i++){
snprintf(strings[i], sizeof(strings[i]), "%s%s", str_serial_config[i], blink_config_data[i]);
}
}
break;
case LINE_SECOND:
blink_delay_cnt++;
snprintf(strings[0], sizeof(strings[0]), "%s", "YOU WANT TO RESET?");
snprintf(strings[1], sizeof(strings[1]), "%s", " PRESS BUTTON");
if(current_cursor == 0){
if(blink_delay_cnt <= 6){
snprintf(strings[2], sizeof(strings[2]), "%s", " [OK / BACK]");
}
else{
snprintf(strings[2], sizeof(strings[2]), "%s", " [ / BACK]");
if(blink_delay_cnt == 12) blink_delay_cnt = 0;
}
}
else{
if(blink_delay_cnt <= 6){
snprintf(strings[2], sizeof(strings[2]), "%s", " [OK / BACK]");
}
else{
snprintf(strings[2], sizeof(strings[2]), "%s", " [OK / ]");
if(blink_delay_cnt == 12) blink_delay_cnt = 0;
}
}
break;
case LINE_THIRD:
copyStringsRange(str_empty_function, strings, 1, 1);
break;
default:
break;
}
break;
default:
break;
}
break;
case SSD1306_PRINT_CH_2:
draw_line_status = DRAW_LINE_OFF;
switch (ssd1306_line_num)
{
case LINE_FIRST:
blink_delay_cnt++;
snprintf(strings[0], sizeof(strings[0]), "%s", "YOU WANT TO DO DHCP?");
snprintf(strings[1], sizeof(strings[1]), "%s", " PRESS BUTTON");
if(current_cursor == 0){
if(blink_delay_cnt <= 6){
snprintf(strings[2], sizeof(strings[2]), "%s", " [OK / BACK]");
}
else{
snprintf(strings[2], sizeof(strings[2]), "%s", " [ / BACK]");
if(blink_delay_cnt == 12) blink_delay_cnt = 0;
}
}
else{
if(blink_delay_cnt <= 6){
snprintf(strings[2], sizeof(strings[2]), "%s", " [OK / BACK]");
}
else{
snprintf(strings[2], sizeof(strings[2]), "%s", " [OK / ]");
if(blink_delay_cnt == 12) blink_delay_cnt = 0;
}
}
break;
case LINE_SECOND:
switch (config_status)
{
case IS_WAITING_FOR_CONFIG:
temp_config_data[0] = dev_config->network_info_common.local_ip[0];
temp_config_data[1] = dev_config->network_info_common.local_ip[1];
temp_config_data[2] = dev_config->network_info_common.local_ip[2];
temp_config_data[3] = dev_config->network_info_common.local_ip[3];
temp_config_data[4] = dev_config->network_info_common.gateway[0];
temp_config_data[5] = dev_config->network_info_common.gateway[1];
temp_config_data[6] = dev_config->network_info_common.gateway[2];
temp_config_data[7] = dev_config->network_info_common.gateway[3];
temp_config_data[8] = dev_config->network_info_common.subnet[0];
temp_config_data[9] = dev_config->network_info_common.subnet[1];
temp_config_data[10] = dev_config->network_info_common.subnet[2];
temp_config_data[11] = dev_config->network_info_common.subnet[3];
temp_config_data[12] = dev_config->options.dns_server_ip[0];
temp_config_data[13] = dev_config->options.dns_server_ip[1];
temp_config_data[14] = dev_config->options.dns_server_ip[2];
temp_config_data[15] = dev_config->options.dns_server_ip[3];
for(i = 0; i < 16; i++){
snprintf(blink_config_data[i], sizeof(blink_config_data[i]), "%d", temp_config_data[i]);
prev_temp_config_data[i] = temp_config_data[i];
}
config_status = CONFIG_DATA_SELECTION;
break;
case CONFIG_DATA_SELECTION:
blink_delay_cnt++;
if(blink_delay_cnt <= 6){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%c%c", 32,32);
if(blink_delay_cnt == 12) blink_delay_cnt = 0;
}
break;
case CONFIG_IN_PROGRESS:
blink_delay_cnt++;
if(blink_delay_cnt <= 1){
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%d", temp_config_data[config_index_cnt]);
}
else{
snprintf(blink_config_data[config_index_cnt], sizeof(blink_config_data[config_index_cnt]), "%c%c", 32,32);
if(blink_delay_cnt == 2) blink_delay_cnt = 0;
}
break;
default:
break;
}
for(i = 0; i < 4; i++){
snprintf(strings[i], sizeof(strings[i]), "%s%s.%s.%s.%s", str_ip_config[i],blink_config_data[(i*4)], blink_config_data[(i*4)+1], blink_config_data[(i*4)+2], blink_config_data[(i*4)+3]);
}
break;
default:
break;
}
break;
default:
break;
}
screen_update_function(strings, 4, current_cursor, draw_line_status);
}
The SSD1306_PRINT_DATA_PROCESS function decides which array and what data to display on the OLED based on the OLED output status values changed by the above button status values. This function stores the output values in a string buffer called strings, and the stored buffer is output through the screen_update_function function declared at the bottom of the function. You can understand it in terms of the MUX concept.
uint8_t set_flag_on_data_change(const uint32_t* prev_array, const uint32_t* current_array, uint16_t array_size) {
int i;
for (i = 0; i < array_size; ++i) {
if (prev_array[i] != current_array[i]) {
return 1; // Arrays are different
}
}
return 0; // Arrays are the same
}
//Cursor & Print Page Decrease Ctrl
void Ctrl_Decrease_Line(int8_t end_line, int8_t end_page){
current_cursor--;
if(current_cursor < 0 && current_page == 0){
current_cursor = 0;
}
else if(current_cursor < 0 && current_page == end_page){
current_page = 0;
current_cursor = end_line;
}
}
//Cursor & Print Page Increase Ctrl
void Ctrl_Increase_Line(int8_t end_line, int8_t end_page){
current_cursor++;
if(current_cursor > end_line && current_page == end_page){
current_cursor = end_line;
}
else if(current_cursor > end_line && current_page == 0){
current_page = end_page;
current_cursor = 0;
}
}
set_flag_on_data_change: This function compares two arrays to check if there are any changes. If the previous array and the current array have different data, it returns 1, and if they are the same, it returns 0. In other words, it's a function that determines whether the contents of two arrays are identical or different. Through this function, if the config data has changed, it decides whether to change the config data based on a flag indicating the data change.
Ctrl_Decrease_Line: This function is responsible for controlling the decrease of the cursor position and the print page. It adjusts the position of the cursor and page when the cursor moves above the first line or cannot go further back from the first page. In particular, it handles the behavior when starting from the last page and ending at the first page.
Ctrl_Increase_Line: This function is responsible for controlling the increase of the cursor position and the print page. It adjusts the position of the cursor and page when the cursor goes beyond the last line or cannot go further forward from the last page. This increases the position of the page and cursor, especially handling cases where it goes beyond the last line or page.
<configmoduleHandler.h>
#include <stdio.h>
#include "common.h"
#include "W7500x_board.h"
#include "W7500x_it.h"
#include "W7500x_i2c.h"
#include "ssd1306.h"
#include "configData.h"
#include "uartHandler.h"
#include "common.h"
#include "dhcp.h"
#define MAX_STRING_LENGTH 22
#define PAGE_FIRST 0
#define PAGE_SECOND 1
#define LINE_FIRST 0
#define LINE_SECOND 1
#define LINE_THIRD 2
#define SSD1306_PRINT_CH_0 0
#define SSD1306_PRINT_CH_1 1
#define SSD1306_PRINT_CH_2 2
#define IS_WAITING_FOR_CONFIG 0
#define CONFIG_DATA_SELECTION 1
#define CONFIG_IN_PROGRESS 2
#define DRAW_LINE_ON 1
#define DRAW_LINE_OFF 0
void Ctrl_Decrease_Line(int8_t end_line, int8_t end_page);
void Ctrl_Increase_Line(int8_t end_line, int8_t end_page);
void Ctrl_Decrease_data(uint32_t* data, int8_t start_num, int8_t end_num);
void Ctrl_Increase_data(uint32_t* data, int8_t start_num, int8_t end_num);
void Config_Module_Btn_Process(void);
void SSD1306_PRINT_DATA_PROCESS(void);
uint8_t set_flag_on_data_change(const uint32_t* prev_array, const uint32_t* current_array, uint16_t array_size);
Video