feat: 06-17 신규 작업본 반영 (개발사양서/기능검토/승인원/Source 등 추가)

.claude/ 제외(.gitignore 추가). 기존 초기커밋(5a96a69) 위에 신규·수정·이동분 커밋.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-18 07:54:58 +09:00
parent 5a96a696b1
commit 096111e983
529 changed files with 12439 additions and 1166 deletions
+3
View File
@@ -36,3 +36,6 @@ desktop.ini
# ── 로그 / 임시 ──
*.log
*.tmp
# ── Claude Code 로컬 설정 ──
.claude/
+61 -10
View File
@@ -1,3 +1,14 @@
■ 작업 기록 규칙 (필수)
- 코드/사양 작업을 하면 그 내용을 `doc` 폴더에 마크다운으로 기록할 것.
- 파일명: `YYMMDD_제목` 형식 (예: `doc/260617_수정내용.md`).
- 같은 날 추가 작업은 그 날짜 파일에 이어서 append.
- 기록 항목: 변경 파일/이유/핵심 결정, 빌드 결과, 미해결/후속 사항.
■ 펌웨어 위치/작업 규칙
- **펌웨어 폴더: `SOURCE/HECO2/`** (User, Library, Makefile, build.sh). 구 `program/`에서 2026-06-17 이동됨 — 이전 문서/메모의 `program/User/...``SOURCE/HECO2/User/...`로 읽을 것.
- `SOURCE/HECO2/User/My_RJ2.c`(룸컨), `My_bunbaegi.c`(각실분배기)는 수정 금지 — 검증된 코드. 문제는 `My_Homenet.c`/`MyMotor.c`/`My_system.c`/`My_Hood.c` 또는 대시보드 쪽에서 해결.
- 펌웨어 수정 후 반드시 빌드 확인: `cd SOURCE/HECO2 && bash build.sh all` (경고/오류 0).
DL 각실제어 시스템 구성
HERV (전열교환기) -(485통신) BUNBAGI -(485통신) 배기(RA) DIFFUSER -(485통신) 급기(SA) DIFFUSER
@@ -49,18 +60,19 @@ HERV 사양
특이사항 : 기저운전/장비보호
(꺼짐예약) : 0 ~ 8 시간, 1시간 단위, 0은 꺼짐
VSP 설정값 (1바이트 0~255, 사양서 DL 대덕연구소 H-ERV 실측표)
VSP 설정값 (1바이트 0~255, 개발사양서 p.12 휴벤 ECO2/좌타입 HRD1-150EPI = 펌웨어 MyControl.c 기본값)
※ 환기 터보-4(250CMH)는 사양서 자동(각실제어) 250 행 값. 기저(50CMH, SA52/EA53)는 대시보드 VSP 9엔트리에서 제외.
| 구분 | 단수 | 풍량(CMH) | VSP SA | VSP EA | 전압 SA(V) | 전압 EA(V) |
|----------|--------|-----------|--------|--------|-----------|-----------|
| 환기 | 약-1 | 100 | 57 | 56 | 3.347 | 3.296 |
| 환기 | 중-2 | 150 | 63 | 61 | 3.634 | 3.571 |
| 환기 | 강-3 | 200 | 69 | 67 | 3.968 | 3.893 |
| 환기 | 터보-4 | 250 | 86 | 85 | 4.391 | 4.125 |
| 바이패스 | 기본 | 150 | 66 | 80 | 3.776 | 4.539 |
| 공청 | 약-1 | 80 | 66 | - | 3.778 | - |
| 공청 | 중-2 | 100 | 70 | - | 4.018 | - |
| 공청 | 강-3 | 120 | 77 | - | 4.354 | - |
| 환기 | 약-1 | 100 | 56 | 57 | 3.30 | 3.35 |
| 환기 | 중-2 | 150 | 63 | 63 | 3.65 | 3.65 |
| 환기 | 강-3 | 200 | 70 | 70 | 4.00 | 4.00 |
| 환기 | 터보-4 | 250 | 86 | 85 | 4.80 | 4.75 |
| 바이패스 | 기본 | 150 | 67 | 75 | 3.85 | 4.25 |
| 공청 | 약-1 | 80 | 65 | - | 3.75 | - |
| 공청 | 중-2 | 100 | 72 | - | 4.10 | - |
| 공청 | 강-3 | 120 | 78 | - | 4.40 | - |
| 공청 | 터보-4 | 150 | 80 | - | 4.50 | - |
VSP 테이블 (VSP ↔ 실측전압, V = VSP × 0.05 + 0.5)
@@ -103,7 +115,46 @@ VSP 테이블 (VSP ↔ 실측전압, V = VSP × 0.05 + 0.5)
회로도 : HERV_MAIN_REV1.1_20240826(회로도).PDF
EEPROM 저장 데이터 (My_define.h EEP_*, page 128B / 엔트리 약 122)
■ NANO100 메모리 맵 (MCU: Nano100SE3BN — LDROM 4K / APROM 115K / Data Flash 8K / SRAM 16K)
출처: DS_Nano100(B)_Series_EN_Rev1.09.pdf (5.2 Memory Organization p.106, 5.6 FMC p.111) + SOURCE/HECO2/Library .../fmc.h, EEPROM_Emulate.h
(1) 시스템 주소공간 (Cortex-M0, 리틀엔디안, 4GB)
| 주소 범위 | 영역 | 비고 |
|---|---|---|
| 0x0000_0000 ~ 0x0001_FFFF | FLASH (코드) | FLASH_BA, 최대 128KB 어드레싱(실제 칩은 123K 프로그램+4K LDROM+Config) |
| 0x2000_0000 ~ 0x2000_3FFF | SRAM 16KB | SRAM_BA |
| 0x4000_0000 ~ 0x401F_FFFF | APB1/APB2 주변장치 | WDT0x40004000·RTC0x40008000·TMR01 0x40010000·I2C0 0x40020000·PWM0 0x40040000·UART0 0x40050000·USBD 0x40060000·ADC12 0x400E0000 / TMR23 0x40110000·UART1 0x40150000·SC0 0x40190000·SC1 0x401B0000·SC2 0x401C0000 |
| 0x5000_0000 ~ 0x5001_FFFF | AHB 주변장치 | GCR 0x50000000·CLK 0x50000200·INT 0x50000300·GPIO 0x50004000·DMA 0x50008000·FMC 0x5000C000·EBI 0x50010000 |
| 0xE000_E000 ~ 0xE000_EFFF | 시스템 제어 | SysTick·NVIC·SCS |
(2) 온칩 플래시 내부 구조 (FMC, 페이지 512B 단위, fmc.h)
| 주소 범위 | 크기 | 영역 | 용도 |
|---|---|---|---|
| 0x0000_0000 ~ 0x0001_CC00 | 115KB | **APROM** (응용 프로그램) | 펌웨어 코드 + EEPROM 에뮬레이션이 여기 안에 있음 |
| 0x0001_CC00 ~ 0x0001_EC00 | 8KB | **Data Flash** | 시작주소 = Config1(DFBA) = 0x0001CC00. **현재 펌웨어 미사용** |
| 0x0010_0000 ~ 0x0010_1000 | 4KB | LDROM (ISP 로더) | 미사용 |
| 0x0030_0000 ~ | - | User Config | CONFIG0=0xFFFFFFFE(CBS 부팅선택 등), CONFIG1=0x0001CC00(DFBA) |
| (APROM+DataFlash 합) 0x0 ~ 0x1EC00 | 123KB | 전체 프로그램 플래시 | DS의 "123K APROM"은 Data Flash 포함 합계(공유) |
(3) 우리가 실제로 쓰는 영역
| 주소 | 크기 | 무엇 | 근거 |
|---|---|---|---|
| 0x0000_0000 ~ 0x0000_B338 | ~46KB | 펌웨어(벡터/코드/rodata/data-init) | build/HERV.bin 크기 (text 43.9K+data 1.9K) |
| 0x0000_B338 ~ 0x0000_FC00 | ~18KB | (빈 APROM) | 코드와 EEPROM 사이 여유 |
| **0x0000_FC00 ~ 0x0000_FFFF** | **1KB (512B×2페이지)** | **EEPROM 에뮬레이션** | `EEP_FLASH_BASE=0xFC00`, `EEP_PAGE_COUNT=2` (EEPROM_Emulate.h). **APROM 내부이며 칩 Data Flash 아님** |
| 0x0000_FFFF ~ 0x0001_CC00 | ~68KB | (빈 APROM) | 미사용 |
| 0x0001_CC00 ~ 0x0001_EC00 | 8KB | 칩 Data Flash | **현재 미사용** (사장님이 FF로 쓰는 곳이 여기 — EEPROM과 다른 영역) |
| 0x2000_0000 ~ 0x2000_3FFF | 16KB | SRAM (gcc_arm.ld) | 스택/힙/.data/.bss |
⚠ 핵심 주의
- **펌웨어 EEPROM(0xFC00, APROM 내부) ≠ 칩 Data Flash(0x1CC00).** 그래서 Nu-Link ICP로 Data Flash에 FF를 써도 EEPROM은 안 지워짐. EEPROM을 비우려면 **칩 이레이즈** 또는 0xFC00 포함 APROM 이레이즈 필요. (`build.sh flash`=program은 코드 섹터만 지워 0xFC00 유지 → 구 EEPROM 잔존)
- **링커 `gcc_arm.ld`는 EEPROM/Data Flash 영역을 예약/보호하지 않음** (FLASH를 0x0~0x20000 통짜로 잡음, 길이 표기도 칩과 불일치). 펌웨어가 0xFC00(63KB)을 넘으면 코드가 EEPROM 위에 얹혀 충돌 — 현재 ~46KB라 여유 있음.
- EEPROM 에뮬레이션 = 2페이지 wear-leveling(EEPROM_Emulate.c). 페이지 매직 0x55AA0001, 엔트리 4B(TAG 0xE5 | idx | ~idx | val), 가득 차면 compact()로 다른 페이지 이동 후 옛 페이지 erase. 논리 인덱스 0~127(128B)을 아래 표대로 사용.
EEPROM 저장 데이터 (논리 인덱스, My_define.h EEP_*, page 128B / 엔트리 약 122)
| 인덱스 | 항목 | 비고 |
|---|---|---|
@@ -0,0 +1,7 @@
<Application x:Class="CvnetPacketProgram.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
@@ -0,0 +1,7 @@
using System.Windows;
namespace CvnetPacketProgram;
public partial class App : Application
{
}
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net10.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UseWPF>true</UseWPF>
<AssemblyName>CvnetPacketProgram</AssemblyName>
<RootNamespace>CvnetPacketProgram</RootNamespace>
<ApplicationManifest>app.manifest</ApplicationManifest>
<!-- 단일 exe 배포 옵션 (publish 시 적용) -->
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.IO.Ports" Version="10.0.0" />
</ItemGroup>
</Project>
@@ -0,0 +1,56 @@
namespace CvnetPacketProgram;
/// <summary>
/// 수신 바이트 스트림에서 0xF7 0x32 로 시작하는 완전한 프레임을 추출한다.
/// 프레임 길이 = 5(Header~Len) + Len + 2(XOR,ADD).
/// </summary>
public sealed class FrameParser
{
private readonly List<byte> _buf = new();
public void Append(byte[] data, int len)
{
for (int i = 0; i < len; i++) _buf.Add(data[i]);
}
/// <summary>버퍼에서 추출 가능한 모든 완전 프레임을 반환한다.</summary>
public List<byte[]> Extract()
{
var result = new List<byte[]>();
while (true)
{
// Header(0xF7) + Device(0x32) 동기화
int sync = FindSync();
if (sync < 0)
{
// 동기 패턴 없음 — 마지막 1바이트(0xF7 가능성)만 남기고 버림
if (_buf.Count > 1) _buf.RemoveRange(0, _buf.Count - 1);
break;
}
if (sync > 0) _buf.RemoveRange(0, sync); // 앞쪽 쓰레기 제거
if (_buf.Count < 5) break; // Len 까지 못 받음
int len = _buf[4];
int frameLen = 5 + len + 2;
if (_buf.Count < frameLen) break; // 프레임 미완성
var frame = _buf.GetRange(0, frameLen).ToArray();
_buf.RemoveRange(0, frameLen);
result.Add(frame);
}
return result;
}
private int FindSync()
{
for (int i = 0; i + 1 < _buf.Count; i++)
if (_buf[i] == Cvnet.Header && _buf[i + 1] == Cvnet.Device)
return i;
// 마지막 바이트가 Header 면 다음 바이트 대기
if (_buf.Count > 0 && _buf[^1] == Cvnet.Header) return _buf.Count - 1;
return -1;
}
public void Clear() => _buf.Clear();
}
@@ -0,0 +1,194 @@
<Window x:Class="CvnetPacketProgram.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="CVNET DL 사양 패킷 통신프로그램 (프로토콜 230824 기준)"
Height="860" Width="1320" MinHeight="600" MinWidth="1000"
FontFamily="Segoe UI" FontSize="13" Background="#F4F5F7">
<Window.Resources>
<Style TargetType="GroupBox">
<Setter Property="Margin" Value="0,0,0,8"/>
<Setter Property="Padding" Value="8"/>
</Style>
<Style TargetType="Button">
<Setter Property="Padding" Value="10,4"/>
<Setter Property="Margin" Value="0,0,6,0"/>
<Setter Property="MinWidth" Value="72"/>
</Style>
<Style x:Key="Mono" TargetType="TextBox">
<Setter Property="FontFamily" Value="Consolas"/>
<Setter Property="FontSize" Value="12.5"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="Background" Value="#1E1E1E"/>
<Setter Property="Foreground" Value="#DDE6EE"/>
<Setter Property="Padding" Value="6"/>
</Style>
<Style x:Key="Lbl" TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="0,0,6,0"/>
<Setter Property="MinWidth" Value="78"/>
</Style>
</Window.Resources>
<DockPanel Margin="8">
<!-- ===== 상단 연결 바 ===== -->
<Border DockPanel.Dock="Top" Background="White" BorderBrush="#D0D5DD" BorderThickness="1"
CornerRadius="6" Padding="10,8" Margin="0,0,0,8">
<StackPanel Orientation="Horizontal">
<TextBlock Text="COM" Style="{StaticResource Lbl}" MinWidth="34"/>
<ComboBox x:Name="CmbPort" Width="100" VerticalAlignment="Center"/>
<Button Content="↻" Click="OnRefreshPorts" Margin="4,0,12,0" MinWidth="30"/>
<TextBlock Text="Baud" Style="{StaticResource Lbl}" MinWidth="40"/>
<ComboBox x:Name="CmbBaud" Width="90" VerticalAlignment="Center"/>
<Button x:Name="BtnOpen" Content="열기" Click="OnToggleOpen" Margin="12,0,6,0" MinWidth="80"/>
<Ellipse x:Name="LedConn" Width="14" Height="14" Fill="#C0392B" VerticalAlignment="Center" Margin="6,0"/>
<TextBlock x:Name="TxtConn" Text="닫힘" VerticalAlignment="Center" Foreground="#475467"/>
</StackPanel>
</Border>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="410"/>
<ColumnDefinition Width="6"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<!-- ===== 좌측 : 패킷 빌더 ===== -->
<Border Grid.Column="0" Background="White" BorderBrush="#D0D5DD" BorderThickness="1" CornerRadius="6">
<ScrollViewer VerticalScrollBarVisibility="Auto" Padding="10">
<StackPanel>
<TextBlock Text="패킷 빌더" FontWeight="Bold" FontSize="15" Margin="0,0,0,8"/>
<Grid Margin="0,0,0,8">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Cmd" Style="{StaticResource Lbl}"/>
<ComboBox x:Name="CmbCmd" Grid.Column="1" SelectionChanged="OnCmdChanged"/>
</Grid>
<Grid Margin="0,0,0,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="Sub ID(hex)" Style="{StaticResource Lbl}"/>
<TextBox x:Name="TxtSubId" Grid.Column="1" Text="01" MaxLength="2"/>
</Grid>
<!-- 모드 / 풍량 / 예약 (제어·응답 공통) -->
<GroupBox x:Name="GrpFields" Header="필드">
<StackPanel>
<Grid Margin="0,0,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="모드" Style="{StaticResource Lbl}"/>
<ComboBox x:Name="CmbMode" Grid.Column="1"/>
</Grid>
<Grid Margin="0,0,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="풍량" Style="{StaticResource Lbl}"/>
<ComboBox x:Name="CmbFan" Grid.Column="1"/>
</Grid>
<WrapPanel Margin="0,2,0,4">
<CheckBox x:Name="ChkBasic" Content="기저모드" Margin="0,2,12,2"/>
<CheckBox x:Name="ChkRange" Content="렌지연동" Margin="0,2,12,2"/>
</WrapPanel>
<!-- 제어 요구(0x51) 전용 Flag -->
<StackPanel x:Name="PnlCtrlFlags">
<TextBlock Text="제어 Flag (요청 항목만 ON)" FontWeight="SemiBold" Margin="0,4,0,2"/>
<WrapPanel>
<CheckBox x:Name="ChkModeFlag" Content="모드Flag" IsChecked="True" Margin="0,2,12,2"/>
<CheckBox x:Name="ChkFanFlag" Content="풍량Flag" IsChecked="True" Margin="0,2,12,2"/>
<CheckBox x:Name="ChkRsvFlag" Content="예약Flag" Margin="0,2,12,2"/>
<CheckBox x:Name="ChkFilterReset" Content="필터타이머리셋" Margin="0,2,12,2"/>
</WrapPanel>
</StackPanel>
<Grid Margin="0,4,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/><ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Text="예약시간(0~24)" Style="{StaticResource Lbl}" MinWidth="100"/>
<TextBox x:Name="TxtReserve" Grid.Column="1" Text="0"/>
</Grid>
</StackPanel>
</GroupBox>
<TextBlock Text="미리보기 (HEX)" FontWeight="SemiBold" Margin="0,4,0,2"/>
<TextBox x:Name="TxtPreview" Style="{StaticResource Mono}" Height="48"/>
<StackPanel Orientation="Horizontal" Margin="0,8,0,0">
<Button Content="빌드" Click="OnBuild"/>
<Button x:Name="BtnSend" Content="전송" Click="OnSendBuilt" Background="#1D6FE0" Foreground="White"/>
</StackPanel>
<Separator Margin="0,12"/>
<TextBlock Text="직접 HEX 전송" FontWeight="SemiBold" Margin="0,0,0,4"/>
<TextBox x:Name="TxtRawHex" Height="44" FontFamily="Consolas"
TextWrapping="Wrap" AcceptsReturn="True"
Text="F7 32 01 11 00"/>
<StackPanel Orientation="Horizontal" Margin="0,6,0,0">
<CheckBox x:Name="ChkAutoSum" Content="XOR/ADD 자동추가" IsChecked="True" VerticalAlignment="Center" Margin="0,0,10,0"/>
<Button Content="HEX 전송" Click="OnSendRaw"/>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Border>
<GridSplitter Grid.Column="1" Width="6" HorizontalAlignment="Stretch" Background="Transparent"/>
<!-- ===== 우측 : 송신/수신 로그 ===== -->
<Grid Grid.Column="2">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="6"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- 송신 로그 -->
<Border Grid.Row="0" Background="White" BorderBrush="#D0D5DD" BorderThickness="1" CornerRadius="6">
<DockPanel>
<Border DockPanel.Dock="Top" Background="#0B3D91" CornerRadius="6,6,0,0" Padding="10,6">
<DockPanel>
<TextBlock Text="▶ 송신 (TX)" Foreground="White" FontWeight="Bold" FontSize="14"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" DockPanel.Dock="Right">
<CheckBox x:Name="ChkTxAutoScroll" Content="자동스크롤" IsChecked="True" Foreground="White" VerticalAlignment="Center" Margin="0,0,10,0"/>
<Button Content="지우기" Click="OnClearTx" MinWidth="60"/>
</StackPanel>
</DockPanel>
</Border>
<TextBox x:Name="TxtTxLog" Style="{StaticResource Mono}" Background="#10243F" BorderThickness="0"/>
</DockPanel>
</Border>
<GridSplitter Grid.Row="1" Height="6" HorizontalAlignment="Stretch" Background="Transparent"/>
<!-- 수신 로그 -->
<Border Grid.Row="2" Background="White" BorderBrush="#D0D5DD" BorderThickness="1" CornerRadius="6">
<DockPanel>
<Border DockPanel.Dock="Top" Background="#0A6B3B" CornerRadius="6,6,0,0" Padding="10,6">
<DockPanel>
<TextBlock Text="◀ 수신 (RX)" Foreground="White" FontWeight="Bold" FontSize="14"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" DockPanel.Dock="Right">
<CheckBox x:Name="ChkRxAutoScroll" Content="자동스크롤" IsChecked="True" Foreground="White" VerticalAlignment="Center" Margin="0,0,10,0"/>
<Button Content="지우기" Click="OnClearRx" MinWidth="60"/>
</StackPanel>
</DockPanel>
</Border>
<TextBox x:Name="TxtRxLog" Style="{StaticResource Mono}" Background="#0E2418" BorderThickness="0"/>
</DockPanel>
</Border>
</Grid>
</Grid>
</DockPanel>
</Window>
@@ -0,0 +1,286 @@
using System.IO.Ports;
using System.Text;
using System.Windows;
using System.Windows.Controls;
namespace CvnetPacketProgram;
public partial class MainWindow : Window
{
private SerialPort? _port;
private readonly FrameParser _parser = new();
public MainWindow()
{
InitializeComponent();
InitUi();
}
// ====================================================================
// 초기화
// ====================================================================
private void InitUi()
{
foreach (var b in new[] { 9600, 19200, 38400, 57600, 115200, 4800, 2400 })
CmbBaud.Items.Add(b);
CmbBaud.SelectedIndex = 0; // 9600 기본
// 송신은 마스터(월패드) 측 요청만 — 응답(0x91/0xD1)은 ERV가 보내며 RX 로그에서 디코딩한다.
CmbCmd.Items.Add(new CmdItem(Cvnet.CmdStatusQuery, "상태 조회 (0x11)"));
CmbCmd.Items.Add(new CmdItem(Cvnet.CmdCtrlReq, "상세 제어 요구 (0x51)"));
foreach (var m in Cvnet.Modes) CmbMode.Items.Add(new ByteItem(m.val, $"0x{m.val:X2} {m.name}"));
foreach (var fobj in Cvnet.Fans) CmbFan.Items.Add(new ByteItem(fobj.val, $"0x{fobj.val:X2} {fobj.name}"));
CmbMode.SelectedIndex = 2; // 수동 일반
CmbFan.SelectedIndex = 1; // 약
RefreshPorts();
CmbCmd.SelectedIndex = 1; // 상세 제어 요구 기본
}
private void RefreshPorts()
{
string? cur = CmbPort.SelectedItem as string;
CmbPort.Items.Clear();
foreach (var p in SerialPort.GetPortNames().OrderBy(NaturalKey))
CmbPort.Items.Add(p);
if (cur != null && CmbPort.Items.Contains(cur)) CmbPort.SelectedItem = cur;
else if (CmbPort.Items.Count > 0) CmbPort.SelectedIndex = 0;
}
private static int NaturalKey(string s)
=> int.TryParse(new string(s.Where(char.IsDigit).ToArray()), out int n) ? n : 0;
private void OnRefreshPorts(object sender, RoutedEventArgs e) => RefreshPorts();
// ====================================================================
// 연결
// ====================================================================
private void OnToggleOpen(object sender, RoutedEventArgs e)
{
if (_port is { IsOpen: true }) { ClosePort(); return; }
if (CmbPort.SelectedItem is not string portName)
{
MessageBox.Show("COM 포트를 선택하세요.", "포트", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
try
{
_port = new SerialPort(portName, (int)CmbBaud.SelectedItem!, Parity.None, 8, StopBits.One)
{
ReadTimeout = 500,
WriteTimeout = 500,
};
_port.DataReceived += OnDataReceived;
_parser.Clear();
_port.Open();
SetConnUi(true, portName);
}
catch (Exception ex)
{
_port = null;
MessageBox.Show($"포트 열기 실패:\n{ex.Message}", "오류", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
private void ClosePort()
{
try
{
if (_port != null)
{
_port.DataReceived -= OnDataReceived;
if (_port.IsOpen) _port.Close();
_port.Dispose();
}
}
catch { /* ignore */ }
_port = null;
SetConnUi(false, null);
}
private void SetConnUi(bool open, string? port)
{
LedConn.Fill = open
? System.Windows.Media.Brushes.LimeGreen
: new System.Windows.Media.SolidColorBrush(
System.Windows.Media.Color.FromRgb(0xC0, 0x39, 0x2B));
TxtConn.Text = open ? $"{port} 연결됨" : "닫힘";
BtnOpen.Content = open ? "닫기" : "열기";
CmbPort.IsEnabled = !open;
CmbBaud.IsEnabled = !open;
}
// ====================================================================
// 수신
// ====================================================================
private void OnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
var sp = _port;
if (sp is not { IsOpen: true }) return;
int n = sp.BytesToRead;
if (n <= 0) return;
var buf = new byte[n];
int read = sp.Read(buf, 0, n);
_parser.Append(buf, read);
var frames = _parser.Extract();
if (frames.Count == 0) return;
Dispatcher.BeginInvoke(() =>
{
foreach (var f in frames)
AppendLog(TxtRxLog, ChkRxAutoScroll, "RX", f, Cvnet.Decode(f));
});
}
catch { /* 수신 중 포트 닫힘 등 무시 */ }
}
// ====================================================================
// Cmd 변경 → 입력 패널 토글
// ====================================================================
private void OnCmdChanged(object sender, SelectionChangedEventArgs e)
{
if (CmbCmd.SelectedItem is not CmdItem ci) return;
bool isQuery = ci.Cmd == Cvnet.CmdStatusQuery;
bool isCtrl = ci.Cmd == Cvnet.CmdCtrlReq;
if (GrpFields != null) GrpFields.Visibility = isQuery ? Visibility.Collapsed : Visibility.Visible;
if (PnlCtrlFlags != null) PnlCtrlFlags.Visibility = isCtrl ? Visibility.Visible : Visibility.Collapsed;
OnBuild(sender, e);
}
// ====================================================================
// 빌드 / 전송
// ====================================================================
private byte[]? BuildPacket()
{
if (CmbCmd.SelectedItem is not CmdItem ci) return null;
byte subId = ParseHexByte(TxtSubId.Text, 0x01);
byte mode = (CmbMode.SelectedItem as ByteItem)?.Val ?? 0x00;
byte fan = (CmbFan.SelectedItem as ByteItem)?.Val ?? 0x00;
byte reserve = ParseDecByte(TxtReserve.Text, 0);
switch (ci.Cmd)
{
case Cvnet.CmdStatusQuery:
return Cvnet.BuildStatusQuery(subId);
case Cvnet.CmdCtrlReq:
return Cvnet.BuildCtrlReq(
subId,
mode, ChkModeFlag.IsChecked == true, ChkBasic.IsChecked == true, ChkRange.IsChecked == true,
fan, ChkFanFlag.IsChecked == true, ChkFilterReset.IsChecked == true,
reserve, ChkRsvFlag.IsChecked == true);
}
return null;
}
private void OnBuild(object sender, RoutedEventArgs e)
{
var pkt = BuildPacket();
if (pkt != null) TxtPreview.Text = Cvnet.Hex(pkt);
}
private void OnSendBuilt(object sender, RoutedEventArgs e)
{
var pkt = BuildPacket();
if (pkt == null) return;
TxtPreview.Text = Cvnet.Hex(pkt);
SendBytes(pkt);
}
private void OnSendRaw(object sender, RoutedEventArgs e)
{
var bytes = ParseHexString(TxtRawHex.Text);
if (bytes.Count == 0)
{
MessageBox.Show("유효한 HEX 바이트가 없습니다.", "HEX", MessageBoxButton.OK, MessageBoxImage.Warning);
return;
}
if (ChkAutoSum.IsChecked == true)
bytes = Cvnet.Finalize(bytes).ToList();
SendBytes(bytes.ToArray());
}
private void SendBytes(byte[] pkt)
{
if (_port is not { IsOpen: true })
{
// 포트 미연결이어도 로그에는 남겨 패킷을 확인할 수 있게 한다.
AppendLog(TxtTxLog, ChkTxAutoScroll, "TX(미연결)", pkt, Cvnet.Decode(pkt));
return;
}
try
{
_port.Write(pkt, 0, pkt.Length);
AppendLog(TxtTxLog, ChkTxAutoScroll, "TX", pkt, Cvnet.Decode(pkt));
}
catch (Exception ex)
{
MessageBox.Show($"전송 실패:\n{ex.Message}", "오류", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
// ====================================================================
// 로그
// ====================================================================
private static void AppendLog(TextBox box, CheckBox autoScroll, string tag, byte[] frame, string decode)
{
var now = DateTime.Now;
var sb = new StringBuilder();
sb.Append('[').Append(now.ToString("HH:mm:ss.fff")).Append("] ")
.Append(tag).Append(" (").Append(frame.Length).Append("B)\n");
sb.Append(" HEX: ").Append(Cvnet.Hex(frame)).Append('\n');
sb.Append(IndentLines(decode)).Append("\n\n");
box.AppendText(sb.ToString());
if (autoScroll.IsChecked == true) box.ScrollToEnd();
}
private static string IndentLines(string s)
{
var lines = s.Replace("\r", "").Split('\n');
return string.Join('\n', lines.Select(l => " " + l));
}
private void OnClearTx(object sender, RoutedEventArgs e) => TxtTxLog.Clear();
private void OnClearRx(object sender, RoutedEventArgs e) => TxtRxLog.Clear();
// ====================================================================
// 파서 유틸
// ====================================================================
private static byte ParseHexByte(string s, byte def)
=> byte.TryParse(s?.Trim().Replace("0x", "", StringComparison.OrdinalIgnoreCase),
System.Globalization.NumberStyles.HexNumber, null, out var v) ? v : def;
private static byte ParseDecByte(string s, byte def)
=> byte.TryParse(s?.Trim(), out var v) ? v : def;
private static List<byte> ParseHexString(string s)
{
var list = new List<byte>();
if (string.IsNullOrWhiteSpace(s)) return list;
var tokens = s.Replace("0x", " ", StringComparison.OrdinalIgnoreCase)
.Replace(",", " ").Replace("\r", " ").Replace("\n", " ").Replace("\t", " ")
.Split(' ', StringSplitOptions.RemoveEmptyEntries);
foreach (var t in tokens)
if (byte.TryParse(t, System.Globalization.NumberStyles.HexNumber, null, out var v))
list.Add(v);
return list;
}
protected override void OnClosed(EventArgs e)
{
ClosePort();
base.OnClosed(e);
}
// 콤보 항목 ----------------------------------------------------------
private sealed record CmdItem(byte Cmd, string Text) { public override string ToString() => Text; }
private sealed record ByteItem(byte Val, string Text) { public override string ToString() => Text; }
}
@@ -0,0 +1,228 @@
using System.Text;
namespace CvnetPacketProgram;
// ============================================================================
// 대림 환기 프로토콜 (20230824 시트) — 구현은 해당 시트 내용만 근거로 함.
//
// 공통 프레임 구조
// Header(0xF7) | Device(0x32) | Sub ID | Cmd | Len | Data[Len] | XOR SUM | ADD SUM
//
// 비트 표기: 시트의 "BIT 8 7 6 5 4 3 2 1" 기준 (bit8 = 0x80(MSB), bit1 = 0x01(LSB))
//
// 체크섬 (시트: "기존 대림 3.0 기준" — 표준 대림 3.0 방식)
// XOR SUM = Header ~ 마지막 Data 까지 전체 XOR
// ADD SUM = (Header ~ XOR SUM 까지 전체 합) & 0xFF
// ============================================================================
public static class Cvnet
{
public const byte Header = 0xF7;
public const byte Device = 0x32;
// Cmd (시트)
public const byte CmdStatusQuery = 0x11; // 상태 조회 (요청) Len 0
public const byte CmdStatusResp = 0x91; // 상태 조회 응답 Len 6
public const byte CmdCtrlReq = 0x51; // 상세 제어 요구 (요청) Len 3
public const byte CmdCtrlResp = 0xD1; // 상세 제어 요구 응답 Len 6
// 모드 상태 (Data 하위 4bit)
public static readonly (byte val, string name)[] Modes =
{
(0x00, "정지(꺼짐)"),
(0x01, "자동 - Matrix(환기)"),
(0x02, "수동 일반(환기)"),
(0x03, "스케쥴(사용안함)"),
(0x04, "바이패스"),
(0x05, "공기청정"),
(0x06, "히터운전(자동포함)"),
(0x0A, "자동 - Matrix(공기청정)"),
};
// 풍량 정도 (bit5~7, 3bit)
public static readonly (byte val, string name)[] Fans =
{
(0x00, "꺼짐"),
(0x01, "약"),
(0x02, "중"),
(0x03, "강"),
};
public static string ModeName(int v) => Lookup(Modes, (byte)(v & 0x0F));
public static string FanName(int v) => Lookup(Fans, (byte)(v & 0x07));
private static string Lookup((byte val, string name)[] table, byte v)
{
foreach (var t in table) if (t.val == v) return t.name;
return $"미정의(0x{v:X2})";
}
public static string CmdName(byte cmd) => cmd switch
{
CmdStatusQuery => "상태 조회",
CmdStatusResp => "상태 조회 응답",
CmdCtrlReq => "상세 제어 요구",
CmdCtrlResp => "상세 제어 요구 응답",
_ => $"미정의 Cmd(0x{cmd:X2})",
};
// ---- 체크섬 ----------------------------------------------------------
public static byte Xor(IReadOnlyList<byte> bytes, int start, int count)
{
byte x = 0;
for (int i = start; i < start + count; i++) x ^= bytes[i];
return x;
}
public static byte Add(IReadOnlyList<byte> bytes, int start, int count)
{
int s = 0;
for (int i = start; i < start + count; i++) s += bytes[i];
return (byte)(s & 0xFF);
}
/// <summary>Header~Data 까지 채워진 프레임에 XOR/ADD 2바이트를 덧붙여 완성한다.</summary>
public static byte[] Finalize(List<byte> body)
{
byte xor = Xor(body, 0, body.Count);
body.Add(xor);
byte add = Add(body, 0, body.Count); // XOR 포함 합
body.Add(add);
return body.ToArray();
}
public static string Hex(IReadOnlyList<byte> b)
{
var sb = new StringBuilder(b.Count * 3);
for (int i = 0; i < b.Count; i++)
{
if (i > 0) sb.Append(' ');
sb.Append(b[i].ToString("X2"));
}
return sb.ToString();
}
// ====================================================================
// 프레임 빌더
// ====================================================================
/// <summary>상태 조회 (0x11), Len 0</summary>
public static byte[] BuildStatusQuery(byte subId)
{
var body = new List<byte> { Header, Device, subId, CmdStatusQuery, 0x00 };
return Finalize(body);
}
/// <summary>상세 제어 요구 (0x51), Len 3</summary>
public static byte[] BuildCtrlReq(
byte subId,
byte mode, bool modeFlag, bool basicMode, bool rangeLink,
byte fan, bool fanFlag, bool filterTimerReset,
byte reserveHour, bool reserveFlag)
{
// Data0: bit8 기저모드, bit7 렌지연동, bit5 모드Flag, bit1~4 모드상태
byte d0 = (byte)(mode & 0x0F);
if (modeFlag) d0 |= 0x10;
if (rangeLink) d0 |= 0x40;
if (basicMode) d0 |= 0x80;
// Data1: bit8 풍량Flag, bit5~7 풍량정도, bit1 필터타이머리셋
byte d1 = (byte)((fan & 0x07) << 4);
if (filterTimerReset) d1 |= 0x01;
if (fanFlag) d1 |= 0x80;
// Data2: bit6 예약Flag, bit1~5 꺼짐예약 설정시간(0x1F=예약끄기/연속)
byte d2 = (byte)(reserveHour & 0x1F);
if (reserveFlag) d2 |= 0x20;
var body = new List<byte> { Header, Device, subId, CmdCtrlReq, 0x03, d0, d1, d2 };
return Finalize(body);
}
// 응답(0x91 상태 응답 / 0xD1 제어 응답)은 ERV가 송신하므로 빌더 없음.
// 수신 프레임은 아래 Decode()에서 해석한다.
// ====================================================================
// 디코더 — 수신 프레임 해석
// ====================================================================
public static string Decode(byte[] f)
{
if (f.Length < 7) return "(길이 부족 — 최소 7바이트)";
var sb = new StringBuilder();
byte subId = f[2];
byte cmd = f[3];
byte len = f[4];
sb.AppendLine($"Header=0x{f[0]:X2} Device=0x{f[1]:X2} Sub ID=0x{subId:X2} Cmd=0x{cmd:X2} ({CmdName(cmd)}) Len={len}");
int dataStart = 5;
int need = 5 + len + 2;
bool lenOk = f.Length >= need;
if (!lenOk)
{
sb.AppendLine($" ! Len 기준 필요 길이 {need}B, 실제 {f.Length}B");
return sb.ToString().TrimEnd();
}
byte rxXor = f[5 + len];
byte rxAdd = f[5 + len + 1];
byte calcXor = Xor(f, 0, 5 + len);
byte calcAdd = Add(f, 0, 5 + len + 1); // XOR 포함
string xorMark = rxXor == calcXor ? "OK" : $"X (계산 0x{calcXor:X2})";
string addMark = rxAdd == calcAdd ? "OK" : $"X (계산 0x{calcAdd:X2})";
switch (cmd)
{
case CmdStatusQuery:
sb.AppendLine(" [상태 조회 요청]");
break;
case CmdCtrlReq when len >= 3:
DecodeCtrlReq(sb, f, dataStart);
break;
case CmdStatusResp when len >= 6:
case CmdCtrlResp when len >= 6:
DecodeResponse(sb, f, dataStart);
break;
default:
if (len > 0)
sb.AppendLine($" Data: {Hex(f[dataStart..(dataStart + len)])}");
break;
}
sb.Append($" XOR=0x{rxXor:X2} [{xorMark}] ADD=0x{rxAdd:X2} [{addMark}]");
return sb.ToString();
}
private static void DecodeCtrlReq(StringBuilder sb, byte[] f, int s)
{
byte d0 = f[s], d1 = f[s + 1], d2 = f[s + 2];
sb.AppendLine(" [상세 제어 요구]");
sb.AppendLine($" Data0=0x{d0:X2} 모드={ModeName(d0 & 0x0F)}"
+ $" 모드Flag={Bit(d0, 0x10)} 렌지연동={Bit(d0, 0x40)} 기저모드={Bit(d0, 0x80)}");
sb.AppendLine($" Data1=0x{d1:X2} 풍량={FanName((d1 >> 4) & 0x07)}"
+ $" 풍량Flag={Bit(d1, 0x80)} 필터타이머리셋={Bit(d1, 0x01)}");
sb.AppendLine($" Data2=0x{d2:X2} 예약설정시간={ReserveSet(d2 & 0x1F)} 예약Flag={Bit(d2, 0x20)}");
}
private static void DecodeResponse(StringBuilder sb, byte[] f, int s)
{
byte d0 = f[s], d1 = f[s + 1], d2 = f[s + 2], d3 = f[s + 3], d4 = f[s + 4], d5 = f[s + 5];
sb.AppendLine($" Data0=0x{d0:X2} [에러] 장비보호={Bit(d0,0x80)} 미세먼지센서={Bit(d0,0x40)} 배기팬={Bit(d0,0x20)} 급기팬={Bit(d0,0x10)} 내부통신(룸콘)={Bit(d0,0x08)} CO2센서={Bit(d0,0x04)} 소자교환={Bit(d0,0x02)} 온/습도센서={Bit(d0,0x01)}");
sb.AppendLine($" Data1=0x{d1:X2} 모드={ModeName(d1 & 0x0F)} 기저모드={Bit(d1,0x80)} 렌지연동={Bit(d1,0x40)}");
sb.AppendLine($" Data2=0x{d2:X2} 풍량={FanName((d2 >> 4) & 0x07)} 필터청소={Bit(d2,0x02)} 필터교환={Bit(d2,0x01)}");
sb.AppendLine($" Data3=0x{d3:X2} 예약설정시간={ReserveSet(d3 & 0x1F)} 예약상태={Bit(d3,0x20)}");
sb.AppendLine($" Data4=0x{d4:X2} 남은시간(시)={d4}");
sb.AppendLine($" Data5=0x{d5:X2} 남은시간(분)={d5}");
}
private static string Bit(byte v, byte mask) => (v & mask) != 0 ? "ON" : "off";
private static string ReserveSet(int v) => v switch
{
0x00 => "0(없음)",
0x1F => "예약끄기(연속)",
_ => $"{v}시간",
};
}
@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="CvnetPacketProgram.app" />
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</windowsSettings>
</application>
</assembly>
@@ -1,489 +0,0 @@
# 각실제어 내부 통신 프로토콜 (Rev 2.0, CMD 기반)
> 휴벤ECO(ERV) ↔ 각실분배기 ↔ 디퓨저 ↔ 룸컨 **내부 RS-485 통신** 규격
>
> 본 문서는 `Protocol/수정_Each_Room_Jushin_protocol_RS485_Rev1.2` (주신전자) 와
> 펌웨어 `program/User/My_Uart.c` (각실분배기/디퓨저 폴링) 구현을 기반으로,
> **CMD 기반으로 단순화·확장**하여 새로 정의한 규격이다.
> (DL 룸컨 232 프로토콜 `My_RJ2.c` 는 DL 사양으로 본 규격과 무관 — 변경하지 않는다.)
- **물리계층** : RS-485, **115200 bps, 8 Data, None Parity, 1 Stop (N81)**
- **토폴로지** : 1 Master(메인보드) ↔ N Slave(디퓨저/룸컨), 메인보드 폴링 방식
- **대상 시스템** : 사양서 5페이지(힘펠 배선도) 구성 = **거실 + 방1~4 (5실)**, 각 실 룸컨
- 디퓨저 : 거실 SA 2·RA 2, 방1~4 각 SA 1·RA 1 → **SA 디퓨저 6 + RA 디퓨저 6**, 룸컨 5
---
## 0. 무엇이 바뀌었나 (Rev 1.2 → Rev 2.0)
| 구분 | 기존 (Rev 1.2) | 개선 (Rev 2.0) |
|------|----------------|----------------|
| 패킷 식별 | `VSP Mode` 값(0x00/0x11/0x12/0x01~03/0x10)에 따라 **같은 byte 위치의 의미가 계속 바뀜** | **CMD 1바이트로 패킷 종류 고정** → 한 패킷은 항상 같은 레이아웃 |
| 거실 공기질 | 별도 모드 0x11 / 0x12 로 방을 쪼개서 전송 | **방별 센서 패킷 1종으로 통합**, ROOM 필드로 구분 |
| 길이 | 29/39 byte 가변, 위치로 추정 | **LEN 필드 명시** → 파싱 단순 |
| 장치 주소 | ID1(종류)+ID2(번호) 혼용, 거실=5 등 불규칙 | **DEV / ROOM / IDX 3필드**로 직관적 주소화 |
| 에러코드 | **16비트 전부 소진** → 방4 추가 불가 (한계) | **32비트로 확장** → 방4 + 향후 여유 |
| 확장성 | 4실 고정 | **5실(거실+방1~4) + 룸컨 5 / SA·RA 디퓨저 각 6** 명시 |
| 역할 정의 | 명령/상태 방향이 패킷마다 섞여 모호 | **버스 마스터=ERV(폴링) / 명령 주체=룸컨 / 실행=ERV→디퓨저** 로 명확화 |
> **제어 권한 정리** : 사용자는 룸컨에서 전원·모드·풍량·예약·필터리셋과 VSP 풍량 테이블을 설정한다.
> 룸컨은 버스상 Slave이므로 이 명령들을 ERV 폴링에 대한 응답(`CMD_ROOMCON`/`CMD_VSP_SET`)으로 올린다.
> ERV는 명령을 받아 분배기를 통해 디퓨저 댐퍼·풍량·LED를 제어하고, 센서값을 읽어 룸컨에 전달한다.
---
## 1. 공통 프레임
```
+------+------+------+------------------+--------+--------+
| STX | CMD | LEN | PAYLOAD[LEN] | CRC_H | CRC_L |
+------+------+------+------------------+--------+--------+
0xAA 1B 1B LEN bytes 16-bit CRC
```
| 필드 | 크기 | 설명 |
|---------|------|------|
| STX | 1 | 고정 `0xAA` |
| CMD | 1 | 명령/응답 코드 (2장) |
| LEN | 1 | PAYLOAD 바이트 수 (0~255) |
| PAYLOAD | LEN | CMD 별 데이터 (3·4장) |
| CRC | 2 | **CRC-16/MODBUS** (poly 0xA001, init 0xFFFF), **CMD~PAYLOAD** 까지, **빅엔디안(CRC_H 먼저)** |
- 모든 멀티바이트 수치는 **빅엔디안(상위 바이트 먼저)**. (CRC 포함, 펌웨어 `My_Uart.c` 관례 유지)
- 프레임 구분 : `STX(0xAA)` 탐색 → `LEN` 으로 길이 확보 → `CRC` 검증.
- 수신 타임아웃(예: 50ms) 내 미완성 프레임은 폐기하고 STX 재탐색.
> **CRC 계산** : `My_Uart.c` 의 `CRC16()` (MODBUS 룩업테이블) 동일. 결과 16비트를 `CRC_H = (crc>>8)`, `CRC_L = (crc&0xFF)` 순으로 전송.
---
## 2. 명령 코드 (CMD)
**버스 레벨과 제어 권한을 구분해서 이해해야 한다.**
- **버스 마스터 = ERV(메인보드)** : 모든 통신을 ERV가 폴링한다. 룸컨/디퓨저는 폴링을 받아야만 송신하는 Slave.
- **제어 권한(명령 발생) = 룸컨** : 사용자가 룸컨에서 전원/모드/풍량/예약/필터리셋, **VSP 풍량 테이블 설정·저장**을 한다.
룸컨은 Slave이므로 이 명령들을 ERV 폴링에 대한 **응답에 실어** ERV로 보낸다 (룸컨 → ERV).
- **실행 = ERV** : 룸컨 명령을 받아 분배기를 통해 **디퓨저 댐퍼 개폐·풍량·LED를 제어**하고, **센서값을 읽어 룸컨에 전달**한다.
즉 데이터 흐름은: **룸컨(명령) → ERV(실행) → 디퓨저(댐퍼/센서) → ERV(센서수집) → 룸컨(표시)**.
CMD 상위 비트로 송신 방향을 구분한다. **0x10~0x7F = ERV(Master) 송신**, **0x90~0xFF = Slave 송신(응답)**.
### 2.1 ERV(메인보드, Master) 송신
| CMD | 이름 | 대상 | PAYLOAD | 설명 |
|------|----------------------|--------|---------|------|
| 0x10 | `CMD_DIFFUSER_CTRL` | 디퓨저 | 4.1 | **ERV가 디퓨저 제어**(댐퍼각/풍량/LED/리셋) + 폴링. ERV가 제어 주체 |
| 0x20 | `POLL_ROOMCON` | 룸컨 | 4.3 | ERV가 룸컨 폴링 + **표시용 데이터 전달**(ERV 동작상태/해당 실 공기질/에러/온도). 명령 수용 결과 echo |
| 0x30 | `RSP_VSP_STATUS` | 룸컨 | 4.5 | 룸컨 요청에 대한 **현재 VSP 풍량 테이블 값 회신**(룸컨 표시용) |
| 0x40 | `POLL_SPEC` | 공통 | 없음 | 장치 사양/버전 요청 |
### 2.2 Slave(룸컨/디퓨저) 송신 = 명령/상태 보고
| CMD | 이름 | 송신자 | PAYLOAD | 설명 |
|------|------------------------|--------|---------|------|
| 0xA0 | `CMD_ROOMCON` | 룸컨 | 4.4 | **룸컨이 사용자 명령 전달**: 전원/모드/풍량/예약/히터·UV/필터리셋 (0x20 응답) |
| 0xB0 | `CMD_VSP_SET` | 룸컨 | 4.6 | **룸컨이 VSP 풍량 테이블 설정·저장** + 장치 개수 설정 (0x20 응답, VSP 세팅모드) |
| 0x90 | `RSP_DIFFUSER_STATUS` | 디퓨저 | 4.2 | 디퓨저 댐퍼각/공기질/RPM/에러/버전 (0x10 응답) |
| 0x91 | `RSP_DIFFUSER_SENSOR` | 디퓨저 | 4.7 | 통합공기질 센서값(PM/온습도/VOC/NOx/CO2) (방별) |
| 0xC0 | `RSP_SPEC` | 공통 | 4.8 | 사양/버전 (0x40 응답) |
> 모든 패킷은 대상 장치 주소(DEV/ROOM/IDX)를 선두에 싣고, 응답은 이를 그대로 에코한다.
> `CMD_ROOMCON`(0xA0)·`CMD_VSP_SET`(0xB0)은 이름은 "CMD"지만 버스상으로는 **룸컨이 ERV 폴링(0x20)에 응답하는 형태**로 전송된다. (룸컨이 명령 주체이기 때문)
---
## 3. 공통 값 정의
### 3.1 장치 주소 (DEV / ROOM / IDX)
각 PAYLOAD 선두 3바이트는 항상 장치 주소다.
| 필드 | 크기 | 값 | 의미 |
|------|------|----|------|
| DEV | 1 | `0x10`=SA 디퓨저, `0x20`=RA 디퓨저, `0x30`=룸컨 | 장치 종류 |
| ROOM | 1 | `1`=거실, `2`=방1, `3`=방2, `4`=방3, `5`=방4 | 실 번호 |
| IDX | 1 | `1`~ | 같은 실·같은 종류 장치의 일련번호 (거실 SA·RA는 `1`,`2`) |
**5실 디바이스 맵 (힘펠 배선도 기준 — SA 6 / RA 6 / 룸컨 5)**
| 실 | ROOM | SA 디퓨저 | RA 디퓨저 | 룸컨 |
|----|------|-----------|-----------|------|
| 거실 | 1 | (0x10,1,1) 거실급기1 · (0x10,1,2) 거실급기2 | (0x20,1,1) 거실배기1 · (0x20,1,2) 거실배기2 | (0x30,1,1) |
| 방1 | 2 | (0x10,2,1) | (0x20,2,1) | (0x30,2,1) |
| 방2 | 3 | (0x10,3,1) | (0x20,3,1) | (0x30,3,1) |
| 방3 | 4 | (0x10,4,1) | (0x20,4,1) | (0x30,4,1) |
| 방4 | 5 | (0x10,5,1) | (0x20,5,1) | (0x30,5,1) |
> 방1~4 구성은 모두 동일(SA 1 · RA 1 · 룸컨 1). 거실만 SA·RA 각 2대.
### 3.2 전원 (Power)
| 값 | 의미 |
|----|------|
| 0x00 | OFF |
| 0x01 | ON |
### 3.3 운전모드 (RunMode)
| 값 | 의미 | 펌웨어 매핑 |
|----|------|-------------|
| 0x01 | 수동(환기) | MODE_VENTILATION |
| 0x02 | 자동 | MODE_AUTO |
| 0x04 | 바이패스 | MODE_BYPASS |
| 0x08 | 공기청정 | MODE_AIRCLEAN |
### 3.4 풍량 (FanSpeed)
| 값 | 의미 |
|----|------|
| 0x00 | OFF/정지 |
| 0x01 | 1단 (약) |
| 0x02 | 2단 (중) |
| 0x03 | 3단 (강) |
| 0x04 | 4단 (터보) |
> 자동/공청 모드에서는 메인보드 로직(부하점수)이 단수를 결정하므로 디퓨저로 보내는 풍량은 계산 결과값.
### 3.5 LED 밝기 (LedDim)
| 값 | 의미 |
|----|------|
| 0x00 | OFF |
| 0x01~0x0A | 1~10단 (10단 최대) |
> 월패드/스마트스위치 UI는 0~9 단계. 0=OFF 포함 시 0~10으로 매핑.
### 3.6 댐퍼 각도 (DamperAngle)
| 값 | 의미 |
|----|------|
| 0x00 | 0° (닫힘) |
| 0x00~0xB4 | 0~180° (0xB4 = 180° 완전개방) |
### 3.7 에러코드 (ErrorCode, **u32 비트맵** — 확장)
| 비트 | 마스크 | 의미 |
|------|--------|------|
| 0 | 0x00000001 | 필터 청소 |
| 1 | 0x00000002 | 필터 교체 |
| 2 | 0x00000004 | 소자 교체 |
| 3 | 0x00000008 | 온도센서 에러 |
| 4 | 0x00000010 | 장비보호 모드 |
| 5 | 0x00000020 | EA 팬 에러 |
| 6 | 0x00000040 | 간헐운전 모드 |
| 7 | 0x00000080 | SA 팬 에러 |
| 8 | 0x00000100 | 통합센서 에러 — 거실 |
| 9 | 0x00000200 | 통합센서 에러 — 방1 |
| 10 | 0x00000400 | 통합센서 에러 — 방2 |
| 11 | 0x00000800 | 통합센서 에러 — 방3 |
| 12 | 0x00001000 | **통합센서 에러 — 방4 (신규)** |
| 16 | 0x00010000 | 통신 에러 — 거실 |
| 17 | 0x00020000 | 통신 에러 — 방1 |
| 18 | 0x00040000 | 통신 에러 — 방2 |
| 19 | 0x00080000 | 통신 에러 — 방3 |
| 20 | 0x00100000 | **통신 에러 — 방4 (신규)** |
> 비트 13~15, 21~31 은 향후 확장용 예약.
---
## 4. PAYLOAD 상세
> 모든 PAYLOAD는 `[DEV][ROOM][IDX]` 3바이트로 시작. (3.1)
> `u16` 은 빅엔디안. 아래 off 는 PAYLOAD 내 상대 오프셋.
### 4.1 `CMD_DIFFUSER_CTRL` (0x10, Master→디퓨저)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x10(SA) 또는 0x20(RA) |
| 3 | 1 | power | 3.2 |
| 4 | 1 | runMode | 3.3 |
| 5 | 1 | fanSpeed | 3.4 |
| 6 | 1 | ledDim | 3.5 (SA 디퓨저만 유효) |
| 7 | 1 | dmpAngle | 3.6 (해당 포트의 댐퍼 목표각) |
| 8 | 1 | dmpReset | 0=정상 / 1=댐퍼 초기화 |
| 9 | 1 | reserveHour | 예약 정지 0~8시간 (0=없음) |
LEN = 10.
### 4.2 `RSP_DIFFUSER_STATUS` (0x90, 디퓨저→Master)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | 요청 에코 |
| 3 | 1 | power | 현재 전원 |
| 4 | 1 | runMode | 현재 운전모드 |
| 5 | 1 | fanSpeed | 현재 풍량 |
| 6 | 1 | ledDim | 현재 LED 밝기 |
| 7 | 1 | dmpAngle | 현재 댐퍼 각도 (3.6) |
| 8 | 2 | rpm | 해당 팬 실측 RPM (u16) |
| 10 | 4 | errorCode | 3.7 (u32) |
| 14 | 2 | version | 예) 0x0117 = Ver 1.23 |
LEN = 16.
### 4.3 `POLL_ROOMCON` (0x20, ERV→룸컨)
ERV가 룸컨을 폴링하면서 **룸컨 화면에 표시할 데이터**(ERV 동작상태·에러·온도)를 전달하고,
직전에 받은 룸컨 명령의 **수용 결과(ackFlags)** 를 에코한다.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | power | ERV 현재 전원 (3.2) |
| 4 | 1 | runMode | ERV 현재 운전모드 (3.3) |
| 5 | 1 | fanSpeed | ERV 현재 풍량 (3.4) |
| 6 | 1 | autoState | 0=분산, 1=집중 (자동모드) |
| 7 | 1 | reserveRemain | 예약 잔여 시간(hour) |
| 8 | 4 | errorCode | ERV 현재 에러 통보 (3.7, u32) |
| 12 | 2 | outTemp | 외기온도 ×10 (signed, ℃) |
| 14 | 2 | inTemp | 내기온도 ×10 (signed, ℃) |
| 16 | 1 | ackFlags | 직전 룸컨 명령 수용 비트(4.4 cmdFlags 동일 배치) |
LEN = 17.
### 4.4 `CMD_ROOMCON` (0xA0, 룸컨→ERV) — **룸컨이 명령 주체**
사용자가 룸컨에서 조작한 명령을 ERV에 전달한다. `cmdFlags`**이번에 실제로 바꾼 항목만** 표시한다(나머지는 무시).
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30, ERV 폴링(0x20)에 대한 응답으로 송신 |
| 3 | 1 | cmdFlags | bit0 power, bit1 runMode, bit2 fanSpeed, bit3 reserveHour, bit4 heaterUV, bit5 filterReset, bit6 ledDim (1=이 필드 명령 유효) |
| 4 | 1 | power | 3.2 |
| 5 | 1 | runMode | 3.3 |
| 6 | 1 | fanSpeed | 3.4 |
| 7 | 1 | reserveHour | 0~8시간 |
| 8 | 1 | heaterUV | bit0=히터, bit4=UV (1=ON) |
| 9 | 1 | filterReset | 1=필터 리셋 |
| 10 | 1 | ledDim | 3.5 (해당 실 디퓨저 LED 밝기) |
| 11 | 2 | version | 룸컨 버전 |
LEN = 13.
> ERV는 받은 명령을 실행(분배기→디퓨저 제어)하고, 다음 `POLL_ROOMCON(0x20)`의 `ackFlags`·동작상태로 결과를 회신한다.
### 4.5 `RSP_VSP_STATUS` (0x30, ERV→룸컨)
룸컨이 현재 VSP 값을 요청(`CMD_VSP_SET` 의 reqStatus=1)하면, ERV가 **저장된 현재 VSP 풍량 테이블**을 회신한다(룸컨 표시용). 레이아웃은 4.6과 동일(끝의 save/장치개수 필드는 제외, vspSelect로 어떤 모드값인지 표시).
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | vspSelect | 회신하는 모드 (`1`=환기/`2`=공청/`3`=바이패스) |
| 4 | 10 | sa1,ea1 … sa5,ea5 | SA/EA 1~5단 VSP (각 1B) |
| 14 | 2 | rpmRefMid | 중(2단) RPM 기준 |
| 16 | 2 | rpmDeltaMid | 중(2단) RPM 허용편차 |
| 18 | 2 | rpmRefHigh | 강(3단) RPM 기준 |
| 20 | 2 | rpmDeltaHigh | 강(3단) RPM 허용편차 |
LEN = 22.
### 4.6 `CMD_VSP_SET` (0xB0, 룸컨→ERV) — **VSP 설정·저장 주체는 룸컨**
룸컨에서 VSP 풍량 테이블을 한 모드씩(vspSelect) 설정하고 ERV에 저장 요청. 폴링할 장치 개수도 함께 설정.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30, ERV 폴링(0x20)에 대한 응답으로 송신 |
| 3 | 1 | vspSelect | `0`=None, `1`=환기, `2`=공청, `3`=바이패스 |
| 4 | 1 | sa1 | SA 1단 VSP |
| 5 | 1 | ea1 | EA 1단 VSP |
| 6 | 1 | sa2 | SA 2단 |
| 7 | 1 | ea2 | EA 2단 |
| 8 | 1 | sa3 | SA 3단 |
| 9 | 1 | ea3 | EA 3단 |
| 10 | 1 | sa4 | SA 4단 |
| 11 | 1 | ea4 | EA 4단 |
| 12 | 1 | sa5 | SA 5단 |
| 13 | 1 | ea5 | EA 5단 |
| 14 | 2 | rpmRefMid | 중(2단) RPM 기준 (환기/공청만) |
| 16 | 2 | rpmDeltaMid | 중(2단) RPM 허용편차 |
| 18 | 2 | rpmRefHigh | 강(3단) RPM 기준 |
| 20 | 2 | rpmDeltaHigh | 강(3단) RPM 허용편차 |
| 22 | 1 | roomconNum | 폴링할 룸컨 수 (1~5) |
| 23 | 1 | saDiffuserNum | 폴링할 SA 디퓨저 수 (2~6) |
| 24 | 1 | raDiffuserNum | 폴링할 RA 디퓨저 수 (2~6) |
| 25 | 1 | modbusId | 외부 홈넷 연동용 ID (선택) |
| 26 | 1 | save | 0=저장안함, 1=EEPROM 저장 |
| 27 | 1 | reqStatus | 1=현재 VSP 값 회신 요청(ERV가 `RSP_VSP_STATUS`로 응답) |
LEN = 28.
### 4.7 `RSP_DIFFUSER_SENSOR` (0x91, 디퓨저→Master)
통합공기질 센서(SEN66) 1실분. 기존 0x11/0x12 분리 모드를 **이 패킷 1종**으로 대체.
| off | 크기 | 필드 | 단위/비고 |
|-----|------|------|-----------|
| 0 | 3 | DEV/ROOM/IDX | 센서 부착 디퓨저(통상 RA, DEV=0x20) |
| 3 | 2 | pm1p0 | ㎍/㎥ |
| 5 | 2 | pm2p5 | ㎍/㎥ |
| 7 | 2 | pm4p0 | ㎍/㎥ |
| 9 | 2 | pm10p0 | ㎍/㎥ |
| 11 | 2 | humidity | %RH ×10 |
| 13 | 2 | temperature | ℃ ×10 (signed) |
| 15 | 2 | voc | TVOC index |
| 17 | 2 | nox | NOx index |
| 19 | 2 | co2 | ppm |
| 21 | 4 | errorCode | 센서/통신 에러 (3.7) |
LEN = 25.
### 4.8 `RSP_SPEC` (0xC0)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | |
| 3 | 2 | version | 펌웨어 버전 |
| 5 | 1 | deviceType | 장치 타입 코드 |
| 6 | 1 | capability | bit0=히터, bit1=UV, bit2=후드연동 … |
LEN = 7.
---
## 5. 동작 시나리오 (폴링)
ERV가 버스 마스터로서 **룸컨 → 디퓨저 순으로 라운드로빈 폴링**하고, 명령은 룸컨이 응답에 실어 올린다.
1. **룸컨 폴링**
- ERV → 룸컨 : `POLL_ROOMCON(0x20)` (ERV 동작상태·해당 실 공기질·온도·에러 전달 + 직전 명령 ack)
- 룸컨 → ERV : 사용자가 조작했으면 `CMD_ROOMCON(0xA0)` (cmdFlags로 바뀐 항목 표시), VSP 설정중이면 `CMD_VSP_SET(0xB0)` 으로 응답
2. **디퓨저 폴링 (ERV가 제어 주체)**
- ERV → 디퓨저 : `CMD_DIFFUSER_CTRL(0x10)` (댐퍼각/풍량/LED 지시)
- 디퓨저 → ERV : `RSP_DIFFUSER_STATUS(0x90)`, 센서 부착 디퓨저는 이어서 `RSP_DIFFUSER_SENSOR(0x91)`
3. **명령 처리 흐름** : 룸컨 명령(0xA0) 수신 → ERV가 운전모드/풍량 결정 → 각 디퓨저에 `CMD_DIFFUSER_CTRL(0x10)`로 댐퍼 개폐·풍량 지시 → 결과를 다음 `POLL_ROOMCON(0x20)`의 ackFlags·동작상태로 룸컨에 회신.
4. **자동/공청 모드** : ERV가 각 실 센서(0x91)로 부하점수·집중/분산 계산 → 디퓨저 댐퍼각·풍량을 `CMD_DIFFUSER_CTRL`로 지시 (사양서 10~11P 로직).
5. **VSP 시운전** : 룸컨이 `CMD_VSP_SET(0xB0)`으로 단별 VSP·RPM·장치개수 설정(save=1 시 ERV가 EEPROM 저장), reqStatus=1이면 ERV가 `RSP_VSP_STATUS(0x30)`로 현재값 회신.
6. **통신 단절** : 폴링 타임아웃 N회 시 ERV가 해당 실 통신에러 비트(3.7 bit16~20) set, 재연결 시 clear.
---
## 6. 펌웨어 반영 메모
- 대상 파일 : `program/User/My_Uart.c` (SC1, 각실분배기/디퓨저), `bunbaegi_parsing()` / `Bunbaegi_Polling()` 를 CMD 기반으로 교체.
- **`My_RJ2.c` (DL 룸컨 232) 는 변경하지 않는다** — DL 사양 별도 유지.
- CRC : 기존 `CRC16()` (MODBUS) 그대로 사용, 전송은 빅엔디안(Hi→Lo).
- 센서/디퓨저 배열은 현행 `[7]` (index 1~6) 유지 가능하나, ROOM(1~5)+IDX 매핑 테이블 1개로 주소→배열 변환.
- 에러코드는 `uint16_t Err_Code`**`uint32_t`** 로 확장 (방4 비트 수용).
---
## 7. 송수신 예제 — 거실 룸컨이 전 실 상태 표시
**목표** : 거실 룸컨에서 모든 방 디퓨저(SA/RA) 댐퍼·LED·센서 + ERV 동작상태(모드/풍량/예약)를 표시.
**전제** : 거실 룸컨은 디퓨저를 직접 못 읽는다. 버스 마스터는 ERV 하나뿐이므로 항상 2단계.
```
① 수집 : ERV ──폴링──> 각 디퓨저(SA/RA) ──상태/센서──> ERV (캐싱)
② 표시 : ERV ──전달──> 거실 룸컨 (화면 표시)
```
> 아래 모든 프레임의 CRC는 **STX(0xAA) 제외, `CMD~PAYLOAD` 구간**에 대한 CRC-16/MODBUS 결과를 빅엔디안(Hi,Lo)으로 붙인 실제 값이다.
> 예시 값 : runMode=`0x02`(자동), fanSpeed=`2`, 댐퍼 `0xB4`=180°(열림)/`0x00`=닫힘, 온도·습도 ×10.
> **폴링 시간** : 1회 폴링(TX 요청 → RX 응답)을 **300ms**로 가정한다. (각 [TX]/[RX] 쌍 = 300ms)
### ① 수집 단계 — ERV가 각 디퓨저를 라운드로빈 폴링
ERV가 `거실SA1 → 거실SA2 → 거실RA1 → 거실RA2 → 방1SA → 방1RA → … → 방4RA` 순으로 폴링. 대표 예 (괄호는 누적시간):
**거실 SA1 디퓨저 폴링/제어**`CMD_DIFFUSER_CTRL(0x10)` *(t=0 ~ 300ms)*
```
[TX] AA 10 0A | 10 01 01 | 01 02 02 05 B4 00 00 | E4 61
STX CMD LEN DEV ROOM IDX power runMode fan led dmp reset reserve
(SA,거실,1) ON 02(자동) 2 5 B4 0 0
```
```
[RX] AA 90 10 | 10 01 01 | 01 02 02 05 B4 03 52 00 00 00 00 01 17 | A6 08
└RSP_DIFFUSER_STATUS power mode fan led dmp rpm=0352(850) err=0(4B) ver=0117
```
**거실 RA1 디퓨저 폴링** — 상태 `RSP_DIFFUSER_STATUS(0x90)` + 센서 `RSP_DIFFUSER_SENSOR(0x91)` *(t=600 ~ 900ms)*
```
[RX] AA 91 19 | 20 01 01 | 00 05 00 08 00 09 00 0B 01 C2 00 DC 00 64 00 01 02 8A | 00 00 00 00 | E8 AF
└센서 (RA,거실,1) pm1=5 pm2.5=8 pm4=9 pm10=11 습45.0% 온22.0℃ voc100 nox1 co2=028A(650) err=0
```
> RA 디퓨저는 한 폴링 슬롯(300ms)에서 상태(0x90)+센서(0x91)를 함께 응답.
> RA2·방1~4 디퓨저도 같은 방식으로 폴링 → ERV가 전 실 댐퍼각/LED/RPM/센서를 모두 캐싱.
**ERV 동작상태를 거실 룸컨에 전달 (+ 룸컨 명령 수신)**`POLL_ROOMCON(0x20)` *(룸컨 폴링 슬롯, 각 300ms)*
```
[TX] AA 20 11 | 30 01 01 | 01 02 02 01 00 | 00 00 00 00 | 00 96 | 00 DC | 00 | B5 61
└ERV→룸컨 (룸컨,거실,1) power mode fan auto=1(집중) reserveRemain=0
err=0(4B) 외기15.0℃ 내기22.0℃ ack=0
[RX] (거실 룸컨이 조작했으면 CMD_ROOMCON(0xA0)/CMD_VSP_SET(0xB0)로 응답, 없으면 빈 응답)
```
### ② 표시 단계 — 전 실 집계 전달
거실 룸컨이 전 실 디퓨저·센서를 한 화면에 표시하려면, ERV가 ①에서 모은 값을 집계해 거실 룸컨에 전달해야 한다.
> **참고(본 규격 미반영 제안)** : 아래 `CMD_ALLROOM_STATUS(0x21)` 는 "전 실 집계"용으로 검토한 예시 패킷이다.
> 정식 채택은 보류 상태이며, 필요 시 별도 협의 후 2·4장에 추가한다.
**헤더(9B)** + **실별 블록(18B) × 5실** :
| 헤더 off | 필드 | 실 블록 off | 필드 |
|---|---|---|---|
| 0~2 | 룸컨 주소(30·01·01) | +0 | roomNo |
| 3 | ERV power | +1,+2 | SA댐퍼1·2 (`0xFF`=없음) |
| 4 | ERV runMode | +3,+4 | RA댐퍼1·2 |
| 5 | ERV fanSpeed | +5 | LED 밝기 |
| 6 | 예약 잔여(h) | +6,+7 | PM2.5 |
| 7 | autoState | +8,+9 | PM10 |
| 8 | roomCount(=5) | +10,+11 | CO2 |
| | | +12,+13 | VOC |
| | | +14,+15 | 온도 ×10 |
| | | +16,+17 | 습도 ×10 |
```
[TX] AA 21 63 | 30 01 01 01 02 02 00 01 05 | <실1..실5 블록> | D9 F4
└CMD_ALLROOM 헤더(LEN=0x63=99) 거실은 SA·RA 2개 모두 사용
실1(거실): 01 B4 B4 B4 B4 05 00 08 00 0B 02 8A 00 64 00 DC 01 C2 SA열림×2,RA열림×2,LED5,PM2.5=8,PM10=11,CO2=650,VOC=100,22.0℃,45.0%
실2(방1) : 02 B4 FF B4 FF 04 00 0C 00 12 02 D0 00 82 00 DD 01 C4 SA/RA 각1, slot2=FF
실3(방2) : 03 00 FF 00 FF 00 00 06 00 09 02 62 00 5A 00 DC 01 C0 댐퍼 닫힘, LED OFF
실4(방3) : 04 B4 FF B4 FF 06 00 14 00 1C 03 2A 00 A0 00 DB 01 C7
실5(방4) : 05 B4 FF B4 FF 03 00 07 00 0A 02 80 00 5F 00 DC 01 C1
```
> 전체 104 byte 1프레임으로 거실 룸컨이 **전 실 SA/RA 댐퍼·LED·센서 + ERV 모드/풍량/예약**을 모두 표시.
### 폴링 주기와 전체 시간 (1회 = 300ms)
5실 구성에서 ERV가 한 바퀴 도는 동안 폴링하는 장치:
| 장치 | 개수 | 폴링 시간 (×300ms) |
|------|------|--------------------|
| SA 디퓨저 (거실2 + 방1~4 각1) | 6 | 1,800 ms |
| RA 디퓨저 (거실2 + 방1~4 각1, 상태+센서 동시) | 6 | 1,800 ms |
| 룸컨 (거실 + 방1~4) | 5 | 1,500 ms |
| **합계 (1주기)** | **17** | **5,100 ms ≈ 5.1초** |
- 거실 룸컨 화면은 **약 5.1초마다 전 실 데이터가 1회 갱신**된다.
- 갱신을 더 빠르게 하려면 : 폴링 시간 단축(예: 200ms → 17×200 = 3.4초), 또는 폴링 대상 축소.
- `0x21` 집계 프레임은 거실 룸컨 폴링 슬롯 안에서 전달되므로 별도 시간이 추가되지 않는다.
```
[1 주기 = 5.1초]
SA1 SA2 RA1 RA2 | 방1SA 방1RA | 방2SA 방2RA | 방3SA 방3RA | 방4SA 방4RA | RC거실 RC방1 RC방2 RC방3 RC방4
└─거실 4슬롯─┘ └─방1 2─┘ └─방2 2─┘ └─방3 2─┘ └─방4 2─┘ └────── 룸컨 5슬롯 ──────┘
각 슬롯 300ms × 17 = 5,100ms
```
### 요약
| 단계 | 방향 | 패킷 | 역할 |
|------|------|------|------|
| ① | ERV→디퓨저 / 디퓨저→ERV | `0x10` / `0x90`,`0x91` | 전 실 댐퍼·LED·센서 수집 |
| ② | ERV→거실룸컨 | `0x20` | ERV 동작상태(모드/풍량/예약) 전달 |
| ② | ERV→거실룸컨 | `0x21` (미반영 제안) | 전 실 디퓨저·센서 집계 전달 |
---
> 본 문서는 내부 통신 재정의 초안(Rev 2.0)이다. 디퓨저/룸컨 펌웨어 담당(주신전자)과
> CMD 코드·필드 세부값을 상호 합의하여 확정한다.
@@ -1,546 +0,0 @@
# 각실제어 내부 통신 프로토콜 (Rev 3.0, 2-Tier 계층형)
> 휴벤ECO(ERV) ↔ **각실분배기** ↔ 디퓨저(SA/RA) · 룸컨 **내부 통신** 규격
>
> 본 규격은 [각실제어_내부프로토콜_Rev2.0_CMD.md](각실제어_내부프로토콜_Rev2.0_CMD.md) 를
> **계층형(2-Tier)** 으로 재구성한 것이다. 분배기 회로도 `Schematic/BUNBAGI_REV4.1_20251124(회로도).pdf`
> 와 펌웨어 `program/User/My_Uart.c` 를 근거로 한다.
> (Rev 2.0 은 그대로 보존하며, 본 Rev 3.0 이 상위 규격이다. DL 룸컨 232 `My_RJ2.c` 는 무관 — 변경 안 함.)
- **물리계층** : RS-485, **115200 bps, 8 Data, None Parity, 1 Stop (N81)**
- **대상 시스템** : 사양서 5페이지 구성 = **거실 + 방1~4 (5실)**
---
## 0. 무엇이 바뀌었나 (Rev 2.0 단일버스 → Rev 3.0 2-Tier)
회로도 분석 결과, 각실분배기는 **자체 MCU(Nuvoton NANO100SE3BN)를 가진 능동 컨트롤러**임이 확인되었다. 따라서 통신을 두 계층으로 분리한다.
| 구분 | Rev 2.0 (단일 버스) | Rev 3.0 (2-Tier) |
|------|---------------------|------------------|
| 버스 구조 | ERV가 모든 디퓨저/룸컨(17대)을 1버스로 직접 폴링 | **상위: ERV↔분배기 1버스 / 하위: 분배기↔실별 디퓨저·룸컨** |
| ERV 폴링 대상 | 17대 | **분배기 1대** |
| 분배기 역할 | 없음(전원·배선 통과) | **하위 5채널 로컬 마스터 + 에러격리 + 포트별 통신상태 LED** |
| 디퓨저 LED 제어 | 디퓨저에 ledDim 전송 | **디퓨저에 ledDim 전송** (유지). 조명 LED는 **RA 디퓨저에만** 있고 ERV→분배기→RA디퓨저로 밝기 제어 |
| 자동운전 판단 | ERV | **ERV** (분배기는 센서수집·명령실행만) |
| 집계 패킷 | 0x21 제안(미반영) | **상위버스 정식 패킷(`RSP_ALLROOM_*`)으로 채택** |
> **하드웨어 근거 (BUNBAGI Rev4.1)** : 상위 `M485`(RS485 1채널, U5, 커넥터 CN3) / 하위 `SA485`(RS485 **5채널**, 실별 RJ45 J1~J5, RX는 8:1 MUX U6로 실 선택, DIR 채널별) / 전원 24V(60W)·3.3V.
> ※ 분배기의 2×74HC595(U10·U12, SA=초록·RA=노랑) LED는 **각 포트 SA/RA 디퓨저의 통신상태 표시등**(분배기 보드 진단용)이며, 프로토콜과 무관하다.
> ※ **방의 조명용 LED는 RA 디퓨저에만 달려 있고**, ERV가 밝기(0~9)를 명령한다 → 분배기가 해당 RA 디퓨저로 전달.
---
## 0-1. Rev 2.0(단일버스) → Rev 3.0(2-Tier) 장단점
> 채택 전 의사결정용 요약. 결론적으로 **하드웨어(분배기 MCU·하위 5채널·SPOF 구조)와 5실 확장 요구를 고려하면 2-Tier 도입 권장**이되, 분배기 펌웨어 신규 개발과 단일 장애점(SPOF) 대비가 전제다.
### ✅ 장점
| # | 항목 | 내용 | 효과 |
|---|------|------|------|
| 1 | **ERV 폴링 부하 격감** | ERV가 17대 직접 폴링 → **분배기 1대만** 상대 | ERV 펌웨어·루프 단순, CPU 여유 |
| 2 | **갱신 속도 향상** | ERV 입장 1주기 **5.1초 → 0.6초** (상·하위 병렬, 하위는 분배기가 빠르게 순환) | 룸컨·대시보드 응답성 ↑ |
| 3 | **버스 트래픽·충돌 감소** | 상위 버스엔 노드 1개, 하위는 5채널로 부하 분산(MUX+채널별 DIR) | 패킷 충돌/재전송 ↓ |
| 4 | **실별 통신에러 격리** | 한 실 디퓨저 고장이 채널 단위로 격리 → 타 실·ERV에 영향 최소 | 가용성 ↑, 원인 국소화 |
| 5 | **신호 무결성·배선 이점** | 하위는 짧은 로컬 세그먼트 5채널 분리, 채널별 종단·DIR | 노이즈·반사 ↓ (긴 데이지체인 대비) |
| 6 | **ERV–분배기 인터페이스 추상화** | ERV는 디퓨저 주소·개수를 몰라도 됨. 디퓨저 증설/사양변경을 **분배기가 흡수** | ERV 코드 변경 없이 하위 확장 |
| 7 | **역할·개발 분담** | ERV(시스템 로직) ↔ 분배기/디퓨저/룸컨(주신) 펌웨어 디커플링 | 병행 개발·유지보수 용이 |
| 8 | **확장성** | 실/디퓨저 추가는 하위에서 처리, 멀티 분배기(`nodeId`) 대비 | 향후 평면 확장 수월 |
| 9 | **MCU 동일(Nano100)** | ERV·분배기 동일 계열 → 프레임/CRC/드라이버 코드 공유 | 개발 재사용 |
### ⚠️ 단점 / 리스크
| # | 항목 | 내용 | 완화책 |
|---|------|------|--------|
| 1 | **분배기 펌웨어 신규 개발** | 하위 마스터 + 상위 슬레이브 + MUX/DIR + 595 + 집계 캐시 로직 필요 | Nano100 공통 드라이버 재사용, `My_Uart.c` 골격 활용 |
| 2 | **지연(latency) 1홉 추가** | 명령이 ERV→분배기→디퓨저 2단. 최악 상위주기+하위주기 합산 | 긴급 제어는 분배기가 즉시 중계, 댐퍼는 비실시간이라 영향 작음 |
| 3 | **상태 동기화 시차** | ERV가 보는 값은 분배기 캐시(직전 하위 폴링 결과) → 한 박자 지연 가능 | 변경 이벤트 우선 보고, 타임스탬프/시퀀스로 정합 |
| 4 | **단일 장애점(SPOF)** | 중앙 분배기 1대 고장 시 **전 실 통신 두절** (단일버스는 ERV-디퓨저 직접이라 무관) | 분배기 워치독·자기진단, 통신두절 시 ERV 안전모드 |
| 5 | **집계 패킷이 큼** | `RSP_ALLROOM_STATUS` 93B 등 → 1프레임 손상 시 전 실 갱신 실패(재전송 단위 큼) | CRC+재요청, 필요 시 실별 분할 응답 옵션 |
| 6 | **디버깅·추적 복잡** | 장애 시 상위/하위/분배기 로직 분리 진단, 버스 스니핑 2곳 | 분배기 진단로그·상태 LED(595), SPEC/버전 패킷 |
| 7 | **프로토콜 2종 관리** | 상위·하위 CMD 세트 2개 정의·문서화·버전관리 | 본 문서 단일화, 프레임 규칙 공통 |
| 8 | **3자 버전 정합** | ERV·분배기·디퓨저/룸컨 펌웨어 호환성 관리 | `SPEC`(0x1F/0x9F) 버전 교환·검증 |
### 한눈에
| 관점 | Rev 2.0 단일버스 | Rev 3.0 2-Tier |
|------|------------------|----------------|
| ERV 부담 | 큼(17대 폴링) | **작음(1대)** |
| 갱신 주기(ERV) | 5.1초 | **0.6초** |
| 분배기 펌웨어 | 불필요 | **필요(신규)** |
| 장애 격리 | 디퓨저별(분배기 무관) | 실별(단, 분배기 SPOF) |
| 확장/유지보수 | ERV가 전부 관리 | **계층 분리로 용이** |
| 구현 난이도 | 낮음 | 중(분배기 추가) |
---
## 1. 시스템 구조
```
[상위 버스: M485 · RS485 1채널] [하위 버스: SA485 · RS485 5채널 (MUX)]
┌── ch1 거실 : SA디퓨저×2, RA디퓨저×2, 룸컨
ERV ───────────────────────── 각실분배기 ─┼── ch2 방1 : SA디퓨저, RA디퓨저, 룸컨
(Master) (Nano100) ├── ch3 방2 : SA디퓨저, RA디퓨저, 룸컨
· 상위 Slave ├── ch4 방3 : SA디퓨저, RA디퓨저, 룸컨
· 하위 Master └── ch5 방4 : SA디퓨저, RA디퓨저, 룸컨
· 포트별 통신상태 LED(74HC595, 진단용)
· 실별 전원(24V)·통신에러 격리
```
**역할 분담**
| 주체 | 책임 |
|------|------|
| **ERV (메인)** | 전열교환기 팬/VSP 제어, **자동운전 판단**(부하점수·집중/분산, 사양서 10~11P), **부가모드(스마트수면/쾌적조리/안심회복)·후드 연동(HOOD-485) 처리**, 분배기에 전원/모드/풍량 + 실별 댐퍼·LED 타겟 하달, 집계상태 수신 |
| **분배기** | 하위 5채널 폴링(실별 SA/RA 디퓨저·룸컨), **댐퍼·LED 명령 중계·실행**, 센서·룸컨명령 수집→ERV에 집계 보고, 실별 통신에러 격리, **포트별 통신상태 표시 LED**(74HC595, 진단용) |
| **디퓨저(SA/RA)** | 댐퍼 구동·각도/RPM 회신, 센서값 회신. **RA 디퓨저는 자체 조명 LED 점등(밝기 0~9)** |
| **룸컨** | 사용자 입력(전원/모드/풍량/예약 등) 보고, ERV 상태 표시 |
**데이터 흐름 (자동운전)**
```
분배기 ──(실별 원시 센서)──> ERV ──[부하점수·집중/분산 계산]──> 실별 댐퍼/풍량/LED 타겟
ERV ──(타겟)──> 분배기 ──(댐퍼·LED 실행 / 디퓨저 제어)──> 각 실
```
---
## 2. 공통 프레임 (상·하위 동일)
```
+------+------+------+------------------+--------+--------+
| STX | CMD | LEN | PAYLOAD[LEN] | CRC_H | CRC_L |
+------+------+------+------------------+--------+--------+
0xAA 1B 1B LEN bytes 16-bit CRC
```
| 필드 | 크기 | 설명 |
|---------|------|------|
| STX | 1 | 고정 `0xAA` |
| CMD | 1 | 명령/응답 코드 (상위 4장 / 하위 5장) |
| LEN | 1 | PAYLOAD 바이트 수 (0~255) |
| PAYLOAD | LEN | CMD 별 데이터 |
| CRC | 2 | **CRC-16/MODBUS** (poly 0xA001, init 0xFFFF), **CMD~PAYLOAD** 까지, **빅엔디안(CRC_H 먼저)** |
- 모든 멀티바이트 수치는 **빅엔디안**. 상·하위 버스 모두 같은 프레임/CRC 규칙을 쓴다.
- 분배기 MCU와 ERV MCU가 동일 계열(Nano100)이므로 CRC·프레임 파서 코드를 공유한다.
---
## 3. 공통 값 정의
### 3.1 전원 (Power)
`0x00`=OFF, `0x01`=ON
### 3.2 운전모드 (RunMode)
| 값 | 의미 | 펌웨어 |
|----|------|--------|
| 0x01 | 수동(환기) | MODE_VENTILATION |
| 0x02 | 자동 | MODE_AUTO |
| 0x04 | 바이패스 | MODE_BYPASS |
| 0x08 | 공기청정 | MODE_AIRCLEAN |
### 3.3 풍량 (FanSpeed)
`0`=정지, `1`=약, `2`=중, `3`=강, `4`=터보
### 3.4 LED 밝기 (LedDim) — **RA 디퓨저 조명**
`0`=OFF, `1`~`9`=1~9단(9=최대). 조명 LED는 **RA 디퓨저에만** 존재(단색, 색온도 3800K). ERV가 실별 밝기를 지시 → 분배기가 해당 실 RA 디퓨저로 전달 → RA 디퓨저가 자체 점등.
> 분배기 보드의 SA(초록)/RA(노랑) LED는 별개로, 포트별 통신상태 표시등이다(프로토콜 무관).
### 3.5 댐퍼 각도 (DamperAngle)
`0x00`=0°(닫힘) ~ `0xB4`=180°(완전개방). 슬롯 미사용 시 `0xFF`(장치 없음).
### 3.6 에러코드 (ErrorCode, **u32 비트맵**)
| 비트 | 마스크 | 의미 |
|------|--------|------|
| 0 | 0x00000001 | 필터 청소 |
| 1 | 0x00000002 | 필터 교체 |
| 2 | 0x00000004 | 소자 교체 |
| 3 | 0x00000008 | 온도센서 에러 |
| 4 | 0x00000010 | 장비보호 모드 |
| 5 | 0x00000020 | EA 팬 에러 |
| 6 | 0x00000040 | 간헐운전 모드 |
| 7 | 0x00000080 | SA 팬 에러 |
| 8~12 | 0x00000100~0x00001000 | 통합센서 에러 — 거실/방1/방2/방3/방4 |
| 16~20 | 0x00010000~0x00100000 | 통신 에러 — 거실/방1/방2/방3/방4 |
### 3.7 실 번호 (Room)
`1`=거실, `2`=방1, `3`=방2, `4`=방3, `5`=방4. (하위버스 MUX 채널 ch1~ch5 와 1:1)
### 3.8 부가모드 (AddMode, 비트맵)
DL 사양 시나리오 모드. 룸컨에서 토글하며 운전모드(3.2)에 덧씌워진다. 여러 비트 동시 가능.
| 비트 | 마스크 | 의미 | 비고 (사양서 8~9P) |
|------|--------|------|--------------------|
| 0 | 0x01 | 스마트수면 | 자동·풍량1단 고정, 1시간마다 CO2 기준 댐퍼 |
| 1 | 0x02 | 쾌적조리 | 렌지후드 연동(아래 3.9), 환기·3단 급기 |
| 2 | 0x04 | 안심회복 | 침실1 음압, 환기·2단 |
> `0x00` = 부가모드 없음. (회복모드 중 수면모드 불가 등 배타조건은 ERV 로직에서 처리)
### 3.9 후드 연동 (Hood, 비트맵)
렌지후드와 전열교환기 연동. 후드 동작 시 ERV도 동작해야 하므로 ERV가 후드 상태를 감지·연동한다(HOOD-485). 쾌적조리(3.8 bit1) 활성 시 적용.
| 비트 | 마스크 | 의미 |
|------|--------|------|
| 0 | 0x01 | 후드연동 활성화(enable) |
| 1 | 0x02 | 후드 현재 동작중(ON) |
> 예: `0x03` = 연동 ON + 후드 가동중 → ERV 환기·3단 급기. `0x00` = 연동 없음.
---
# 상위 버스 — ERV ↔ 각실분배기
> ERV(Master)가 분배기(유일 Slave)를 폴링한다. 분배기는 하위에서 모은 전 실 데이터를 **집계해 응답**한다.
> 멀티 분배기 확장 대비로 페이로드 선두에 `nodeId`(분배기 번호, 기본 `0x01`)를 둔다.
## 4. 상위 CMD 및 PAYLOAD
| CMD | 이름 | 방향 | PAYLOAD | 설명 |
|------|------|------|---------|------|
| 0x10 | `CMD_SYSTEM` | ERV→분배기 | 4.1 | 전원/모드/풍량/예약 + 실별 댐퍼·LED 타겟 (폴링 겸용) |
| 0x12 | `POLL_SENSOR` | ERV→분배기 | nodeId(1) | 전 실 센서 집계 요청 |
| 0x14 | `CMD_CONFIG` | ERV→분배기 | 4.5 | VSP 테이블·장치개수·ID 설정/저장 |
| 0x1F | `POLL_SPEC` | ERV→분배기 | nodeId(1) | 분배기 사양/버전 요청 |
| 0x90 | `RSP_ALLROOM_STATUS` | 분배기→ERV | 4.2 | 전 실 댐퍼·RPM·LED·룸컨명령·에러 집계 (0x10 응답) |
| 0x92 | `RSP_ALLROOM_SENSOR` | 분배기→ERV | 4.3 | 전 실 통합공기질 센서 집계 (0x12 응답) |
| 0x94 | `RSP_CONFIG` | 분배기→ERV | 4.5 | 설정 에코/저장결과 (0x14 응답) |
| 0x9F | `RSP_SPEC` | 분배기→ERV | 4.6 | 분배기 사양/버전 |
### 4.1 `CMD_SYSTEM` (0x10, ERV→분배기)
**글로벌(off 0~15, 16B)** + **실별 타겟 블록(6B) × 5실**
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 1 | nodeId | 분배기 번호(0x01) |
| 1 | 1 | power | 3.1 |
| 2 | 1 | runMode | 3.2 |
| 3 | 1 | fanSpeed | 3.3 |
| 4 | 1 | addMode | 부가모드 비트맵 (3.8) |
| 5 | 1 | hood | 후드 연동 비트맵 (3.9) |
| 6 | 1 | reserveHour | 0~8시간 |
| 7 | 4 | errorCode | ERV 시스템 에러 통보 (3.6) |
| 11 | 2 | outTemp | 외기온도 ×10 (signed) |
| 13 | 2 | inTemp | 내기온도 ×10 (signed) |
| 15 | 1 | roomCount | 실 수(=5) |
실별 타겟 블록(6B, roomCount회 반복) :
| off(상대) | 크기 | 필드 | 비고 |
|-----------|------|------|------|
| +0 | 1 | roomNo | 3.7 |
| +1 | 1 | saDamper1 | SA 디퓨저1 목표각 (3.5) |
| +2 | 1 | saDamper2 | SA 디퓨저2 (거실만, 그 외 0xFF) |
| +3 | 1 | raDamper1 | RA 디퓨저1 목표각 |
| +4 | 1 | raDamper2 | RA 디퓨저2 (거실만, 그 외 0xFF) |
| +5 | 1 | ledDim | 해당 실 RA 디퓨저 조명 밝기 (3.4) |
LEN = 16 + 6×5 = **46**.
### 4.2 `RSP_ALLROOM_STATUS` (0x90, 분배기→ERV)
**글로벌(8B)** + **실별 상태 블록(17B) × 5실**
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 1 | nodeId | |
| 1 | 1 | bunbagiState | 분배기 동작/에러 요약 |
| 2 | 1 | addModeReq | 룸컨이 요청한 부가모드 비트맵 (3.8) |
| 3 | 4 | errorCode | 전 실 통신·센서 에러 집계 (3.6) |
| 7 | 1 | roomCount | =5 |
실별 상태 블록(17B) :
| off(상대) | 크기 | 필드 | 비고 |
|-----------|------|------|------|
| +0 | 1 | roomNo | |
| +1 | 1 | saDamper1 | 실제 각도 |
| +2 | 1 | saDamper2 | (없으면 0xFF) |
| +3 | 1 | raDamper1 | |
| +4 | 1 | raDamper2 | |
| +5 | 2 | saRpm | SA 팬 실측 RPM |
| +7 | 2 | raRpm | RA 팬 실측 RPM |
| +9 | 1 | ledDim | 현재 RA 조명 LED 밝기 |
| +10 | 1 | rcCmdFlags | 룸컨 명령 비트(아래 5.5 cmdFlags 동일, bit7=부가모드 변경) |
| +11 | 1 | rcPower | 룸컨 설정 전원 |
| +12 | 1 | rcRunMode | 룸컨 설정 모드 |
| +13 | 1 | rcFanSpeed | 룸컨 설정 풍량 |
| +14 | 1 | rcReserveHour | 룸컨 설정 예약 |
| +15 | 1 | rcHeaterUV | bit0=히터,bit4=UV |
| +16 | 1 | rcFilterReset | 1=필터리셋 요청 |
LEN = 8 + 17×5 = **93**.
> `rcCmdFlags` 가 0 이 아니면, 해당 실 룸컨에서 사용자 조작이 발생했다는 뜻 → ERV가 수용해 운전상태 갱신.
### 4.3 `RSP_ALLROOM_SENSOR` (0x92, 분배기→ERV)
**글로벌(2B)** + **실별 센서 블록(19B) × 5실**
| off | 크기 | 필드 |
|-----|------|------|
| 0 | 1 | nodeId |
| 1 | 1 | roomCount(=5) |
실별 센서 블록(19B) :
| off(상대) | 크기 | 필드 | 단위 |
|-----------|------|------|------|
| +0 | 1 | roomNo | |
| +1 | 2 | pm1p0 | ㎍/㎥ |
| +3 | 2 | pm2p5 | ㎍/㎥ |
| +5 | 2 | pm4p0 | ㎍/㎥ |
| +7 | 2 | pm10p0 | ㎍/㎥ |
| +9 | 2 | humidity | %RH ×10 |
| +11 | 2 | temperature | ℃ ×10 (signed) |
| +13 | 2 | voc | TVOC index |
| +15 | 2 | nox | NOx index |
| +17 | 2 | co2 | ppm |
LEN = 2 + 19×5 = **97**.
### 4.5 `CMD_CONFIG` (0x14) / `RSP_CONFIG` (0x94)
VSP 풍량 테이블·장치개수·Modbus ID 설정.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 1 | nodeId | |
| 1 | 1 | vspSelect | 0=None,1=환기,2=공청,3=바이패스 |
| 2 | 10 | sa1,ea1 … sa5,ea5 | 단별 VSP (각 1B) |
| 12 | 2 | rpmRefMid | 중 RPM 기준 |
| 14 | 2 | rpmDeltaMid | 중 RPM 편차 |
| 16 | 2 | rpmRefHigh | 강 RPM 기준 |
| 18 | 2 | rpmDeltaHigh | 강 RPM 편차 |
| 20 | 1 | roomconNum | 룸컨 수(1~5) |
| 21 | 1 | saDiffuserNum | SA 디퓨저 수(2~6) |
| 22 | 1 | raDiffuserNum | RA 디퓨저 수(2~6) |
| 23 | 1 | modbusId | 외부 홈넷 연동 ID |
| 24 | 1 | save | 1=EEPROM 저장 |
LEN = 25. `RSP_CONFIG` 는 동일 레이아웃 에코 + save 결과.
### 4.6 `RSP_SPEC` (0x9F)
| off | 크기 | 필드 |
|-----|------|------|
| 0 | 1 | nodeId |
| 1 | 2 | version (예 0x0117=Ver1.23) |
| 3 | 1 | deviceType |
| 4 | 1 | capability (bit0 히터/bit1 UV/bit2 후드연동) |
LEN = 5.
---
# 하위 버스 — 각실분배기 ↔ 디퓨저 · 룸컨
> 분배기(로컬 Master)가 **MUX로 실 채널(ch1~ch5)을 선택**한 뒤 그 실의 SA/RA 디퓨저·룸컨을 폴링한다.
> 조명 LED(RA 디퓨저)는 `LCMD_DIFFUSER` 의 `ledDim` 으로 제어한다(3.4). 분배기 보드의 74HC595 LED는 별개(포트별 통신상태 표시, 진단용).
## 5. 하위 CMD 및 PAYLOAD
PAYLOAD 선두 3바이트는 장치 주소 `[DEV][ROOM][IDX]`.
- DEV : `0x10`=SA 디퓨저, `0x20`=RA 디퓨저, `0x30`=룸컨
- ROOM : 3.7 (채널과 1:1) / IDX : 같은 실·종류 일련번호(거실 SA·RA는 1,2)
| CMD | 이름 | 방향 | PAYLOAD | 설명 |
|------|------|------|---------|------|
| 0x20 | `LCMD_DIFFUSER` | 분배기→디퓨저 | 5.1 | 디퓨저 댐퍼/풍량 제어 + 폴링 |
| 0x21 | `LPOLL_ROOMCON` | 분배기→룸컨 | 5.4 | 룸컨 폴링 + ERV 상태 표시데이터 전달 |
| 0xA0 | `LRSP_DIFFUSER` | 디퓨저→분배기 | 5.2 | 댐퍼각/RPM/에러/버전 (0x20 응답) |
| 0xA1 | `LRSP_DIFFUSER_SENSOR` | 디퓨저→분배기 | 5.3 | 통합공기질 센서 (방별, 센서 부착 디퓨저) |
| 0xB0 | `LRSP_ROOMCON` | 룸컨→분배기 | 5.5 | 룸컨 사용자 명령 (0x21 응답) |
### 5.1 `LCMD_DIFFUSER` (0x20, 분배기→디퓨저)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x10(SA)/0x20(RA) |
| 3 | 1 | power | 3.1 |
| 4 | 1 | runMode | 3.2 |
| 5 | 1 | fanSpeed | 3.3 |
| 6 | 1 | ledDim | RA 디퓨저 조명 밝기 (3.4) — **RA(0x20)만 유효, SA는 0** |
| 7 | 1 | dmpAngle | 목표 댐퍼각 (3.5) |
| 8 | 1 | dmpReset | 1=댐퍼 초기화 |
LEN = 9.
### 5.2 `LRSP_DIFFUSER` (0xA0, 디퓨저→분배기)
| off | 크기 | 필드 |
|-----|------|------|
| 0 | 3 | DEV/ROOM/IDX (에코) |
| 3 | 1 | power |
| 4 | 1 | runMode |
| 5 | 1 | fanSpeed |
| 6 | 1 | ledDim (현재 RA 조명 밝기, SA는 0) |
| 7 | 1 | dmpAngle (현재각) |
| 8 | 2 | rpm |
| 10 | 4 | errorCode (3.6) |
| 14 | 2 | version |
LEN = 16.
### 5.3 `LRSP_DIFFUSER_SENSOR` (0xA1, 디퓨저→분배기)
| off | 크기 | 필드 | 단위 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | 센서 부착 디퓨저(통상 RA) |
| 3 | 2 | pm1p0 | ㎍/㎥ |
| 5 | 2 | pm2p5 | ㎍/㎥ |
| 7 | 2 | pm4p0 | ㎍/㎥ |
| 9 | 2 | pm10p0 | ㎍/㎥ |
| 11 | 2 | humidity | %RH ×10 |
| 13 | 2 | temperature | ℃ ×10 |
| 15 | 2 | voc | TVOC |
| 17 | 2 | nox | NOx |
| 19 | 2 | co2 | ppm |
| 21 | 4 | errorCode | 3.6 |
LEN = 25.
### 5.4 `LPOLL_ROOMCON` (0x21, 분배기→룸컨)
분배기가 ERV로부터 받은 동작상태를 룸컨에 전달(표시용) + 룸컨 명령 회수.
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | power | ERV 현재 전원 |
| 4 | 1 | runMode | ERV 현재 모드 |
| 5 | 1 | fanSpeed | ERV 현재 풍량 |
| 6 | 1 | addMode | 현재 부가모드 비트맵 (3.8) |
| 7 | 1 | hood | 후드 연동 상태 (3.9) |
| 8 | 1 | reserveRemain | 예약 잔여(h) |
| 9 | 4 | errorCode | 3.6 |
| 13 | 2 | outTemp | ×10 |
| 15 | 2 | inTemp | ×10 |
| 17 | 1 | ackFlags | 직전 룸컨 명령 수용 비트 |
LEN = 18.
### 5.5 `LRSP_ROOMCON` (0xB0, 룸컨→분배기)
| off | 크기 | 필드 | 비고 |
|-----|------|------|------|
| 0 | 3 | DEV/ROOM/IDX | DEV=0x30 |
| 3 | 1 | cmdFlags | bit0 power,1 runMode,2 fanSpeed,3 reserveHour,4 heaterUV,5 filterReset,6 ledDim,**7 addMode** |
| 4 | 1 | power | 3.1 |
| 5 | 1 | runMode | 3.2 |
| 6 | 1 | fanSpeed | 3.3 |
| 7 | 1 | reserveHour | 0~8 |
| 8 | 1 | heaterUV | bit0 히터,bit4 UV |
| 9 | 1 | filterReset | 1=리셋 |
| 10 | 1 | addMode | 부가모드 토글 비트맵 (3.8) |
| 11 | 2 | version | |
LEN = 13.
> 룸컨이 보낸 명령은 분배기가 모아 상위 `RSP_ALLROOM_STATUS` 의 `rc*` 필드로 ERV에 전달 → ERV가 판단 후 다시 하달.
---
## 6. 동작 시나리오 & 폴링 타이밍
**두 버스가 독립적으로 동작**한다.
**하위 버스 (분배기 로컬 루프)** — 분배기가 ch1~ch5를 MUX로 돌며 각 실의 SA/RA 디퓨저·룸컨 폴링. 케이블이 짧고 전용 채널이라 빠르게 순환하며 전 실 상태를 캐싱.
**상위 버스 (ERV 루프)** — ERV는 **분배기 1대만** 주기적으로 폴링:
1. ERV → 분배기 `CMD_SYSTEM(0x10)` (전원/모드/풍량 + 실별 댐퍼·LED 타겟) → 분배기 `RSP_ALLROOM_STATUS(0x90)` (전 실 댐퍼·RPM·LED·룸컨명령·에러)
2. ERV → 분배기 `POLL_SENSOR(0x12)` → 분배기 `RSP_ALLROOM_SENSOR(0x92)` (전 실 센서)
3. ERV가 센서로 **부하점수·집중/분산 계산**(사양서 10~11P) → 다음 `CMD_SYSTEM` 의 실별 댐퍼/LED/풍량 타겟에 반영
4. 룸컨 조작은 `RSP_ALLROOM_STATUS.rcCmdFlags`(+`addModeReq`) 로 ERV에 보고 → ERV 수용 → 다음 `CMD_SYSTEM` 으로 반영
5. **부가모드(3.8)** : 룸컨에서 스마트수면/쾌적조리/안심회복 토글 → ERV가 해당 시나리오 로직 수행(댐퍼·풍량 타겟 조정) → `CMD_SYSTEM.addMode` 로 현재 상태 회신(룸컨 표시)
6. **후드 연동(3.9)** : ERV가 HOOD-485로 후드 ON 감지 → (쾌적조리 활성 시) ERV 환기·3단 급기 동작 → `CMD_SYSTEM.hood` 로 후드 상태를 분배기·룸컨에 전달. 후드 OFF 시 이전 모드 복귀
7. 통신 단절 : 분배기가 실별 통신에러 비트(3.6)를 set 해 ERV에 보고, 재연결 시 clear
### 폴링 시간 (1회 = 300ms 가정)
| 버스 | 폴링 대상 | 1주기 |
|------|-----------|-------|
| **상위 (ERV↔분배기)** | 2회 (CMD_SYSTEM + POLL_SENSOR) | **600 ms** |
| 하위 (분배기↔실) | 17회(SA6+RA6+룸컨5) — **로컬에서 병렬 진행** | 분배기 내부에서 순환(ERV와 무관) |
> Rev 2.0 은 ERV가 17대를 직접 폴링 → 1주기 **5.1초**.
> Rev 3.0 은 ERV 입장에서 **0.6초**면 전 실 상태를 받는다. 하위 루프는 분배기가 별도로 빠르게 순환하므로 ERV 주기와 분리된다. → **갱신 약 8배 빨라지고 ERV 부하 격감.**
---
## 7. 펌웨어 반영 메모
- **분배기 펌웨어(Nano100)** : 신규. UART1(`SA485`, PB.4/PB.5)=하위 로컬 마스터, UART2(`M485`, PA.8/PA.9)=상위 슬레이브. MUX(SA_MUX_A/B/C/EN)로 채널 선택, DIR(SA485_DIR_01~05) 채널별. 74HC595(LED_DS/SCK/LCK)는 **포트별 SA/RA 통신상태 표시 LED** 구동(진단용). 방 조명 LED는 RA 디퓨저가 자체 점등하므로 ledDim 명령만 중계.
- **ERV 펌웨어** : `My_Uart.c` 의 17대 직접 폴링 → **분배기 1대 상위 프로토콜**로 교체. 자동로직(부하점수·집중/분산)은 ERV에 유지.
- **`My_RJ2.c`(DL 룸컨 232)는 변경하지 않는다.**
- CRC : 기존 `CRC16()`(MODBUS) 공유, 빅엔디안(Hi→Lo).
- 에러코드 `uint32_t` (방4 비트 수용).
---
## 8. 송수신 예제
> 모든 프레임 CRC는 **STX 제외 `CMD~PAYLOAD`** 구간 CRC-16/MODBUS(빅엔디안)의 실제 계산값.
> 예시 : runMode=`0x02`(자동), fan=`2`(중), addMode=`0x02`(쾌적조리), hood=`0x03`(연동ON+가동중), 댐퍼 `0xB4`=열림/`0x00`=닫힘/`0xFF`=없음, 온·습도 ×10. 폴링 1회=300ms.
### 8-A. 상위 버스 (ERV ↔ 분배기)
**① ERV → 분배기 : 전원ON·자동·풍량2·쾌적조리·후드가동 + 실별 댐퍼/LED 타겟** — `CMD_SYSTEM(0x10)` *(t=0~300ms)*
```
[TX] AA 10 2E | 01 01 02 02 02 03 00 00000000 0096 00DC 05 | <실1..5 타겟 6B> | AA 01
CMD LEN node pw md fan add hood rsv err 외15℃ 내22℃ rooms=5
↑쾌적조리 ↑후드연동ON+가동
실1(거실): 01 B4 B4 B4 B4 05 (SA1·SA2·RA1·RA2 열림, RA조명 LED 5)
실2(방1) : 02 B4 FF B4 FF 04
실3(방2) : 03 00 FF 00 FF 00 (댐퍼 닫힘, LED OFF)
실4(방3) : 04 B4 FF B4 FF 06
실5(방4) : 05 B4 FF B4 FF 03
```
**② 분배기 → ERV : 전 실 상태 집계** — `RSP_ALLROOM_STATUS(0x90)`
```
[RX] AA 90 5D | 01 00 02 00000000 05 | <실1..5 상태 17B> | C5 31
node bunSt addModeReq=02 err rooms=5
실1(거실): 01 B4 B4 B4 B4 0352 0334 05 00 01 02 02 00 00 00
roomNo SA1 SA2 RA1 RA2 saRpm=850 raRpm=820 ledDim | rcFlags pw md fan rsv hu fr
실2(방1) : 02 B4 FF B4 FF 0348 032A 04 00 01 02 02 00 00 00
실3(방2) : 03 00 FF 00 FF 0000 0000 00 00 01 02 02 00 00 00
실4(방3) : 04 B4 FF B4 FF 034D 032F 06 00 01 02 02 00 00 00
실5(방4) : 05 B4 FF B4 FF 0350 0332 03 00 01 02 02 00 00 00
```
**③ ERV → 분배기 : 센서 요청 / 분배기 응답** — `POLL_SENSOR(0x12)``RSP_ALLROOM_SENSOR(0x92)` *(t=300~600ms)*
```
[TX] AA 12 01 | 01 | <CRC>
[RX] AA 92 61 | 01 05 | <실1..5 센서 19B> | DC 05
실1(거실): 01 0005 0008 0009 000B 01C2 00DC 0064 0001 028A
roomNo pm1 pm2.5 pm4 pm10 습45.0% 온22.0℃ voc100 nox1 co2=650
실2(방1) : 02 0007 000C 000D 0012 01C4 00DD 0082 0001 02D0 (co2=720)
실3(방2) : 03 0004 0006 0007 0009 01C0 00DC 005A 0001 0262 (co2=610)
실4(방3) : 04 0009 0014 0016 001C 01C7 00DB 00A0 0002 032A (co2=810)
실5(방4) : 05 0005 0007 0008 000A 01C1 00DC 005F 0001 0280 (co2=640)
```
> ERV는 ②③으로 **전 실 상태+센서를 0.6초만에** 확보 → 부하점수·집중/분산 계산 → 다음 `CMD_SYSTEM` 타겟 갱신.
### 8-B. 하위 버스 (분배기 ↔ 디퓨저/룸컨) — 분배기 로컬 루프
**거실 RA1 디퓨저 제어/폴링**`LCMD_DIFFUSER(0x20)``LRSP_DIFFUSER(0xA0)` (RA = 조명 LED 보유)
```
[TX] AA 20 09 | 20 01 01 | 01 02 02 05 B4 00 | 6E 2B (RA,거실,1 / power mode fan led=5 dmp=B4 reset=0)
[RX] AA A0 10 | 20 01 01 | 01 02 02 05 B4 0352 00000000 0117 | ... (led현재5, dmp B4, rpm850, err0, ver1.23)
```
> SA 디퓨저는 LED가 없으므로 `ledDim=0`. 예) 거실 SA1 TX: `AA 20 09 10 01 01 01 02 02 00 B4 00 6E 6F` → RX `AA A0 10 10 01 01 01 02 02 00 B4 03 52 00 00 00 00 01 17 B9 17`.
**거실 RA1 디퓨저 센서**`LRSP_DIFFUSER_SENSOR(0xA1)`
```
[RX] AA A1 19 20 01 01 00 05 00 08 00 09 00 0B 01 C2 00 DC 00 64 00 01 02 8A 00 00 00 00 58 AE
(RA,거실,1) pm1=5 pm2.5=8 pm4=9 pm10=11 습45.0% 온22.0℃ voc100 nox1 co2=650 err0
```
**거실 룸컨 폴링**`LPOLL_ROOMCON(0x21)``LRSP_ROOMCON(0xB0)`
```
[TX] AA 21 12 30 01 01 01 02 02 02 03 00 00 00 00 00 00 96 00 DC 00 92 FA
(ERV상태 전달: 자동·풍량2·쾌적조리(02)·후드연동ON+가동(03))
[RX] AA B0 0D 30 01 01 80 01 02 02 00 00 00 02 01 10 34 4D
cmdFlags=80(부가모드 변경) ... addMode=02(쾌적조리 토글) ver0x0110
```
> 룸컨이 부가모드(쾌적조리)를 토글하면 `cmdFlags` bit7=1·`addMode`=0x02 로 보고 → 분배기가 상위 `RSP_ALLROOM_STATUS.addModeReq`·`rcCmdFlags`에 실어 ERV에 전달 → ERV가 후드연동 운전 수행.
---
> 본 문서는 2-Tier 재정의 초안(Rev 3.0)이다. 분배기/디퓨저/룸컨 펌웨어 담당과 CMD 코드·필드 세부값을 상호 합의하여 확정한다.
+32
View File
@@ -100,6 +100,38 @@
</Setter>
</Style>
<!-- 프리셋모드 선택 버튼(ECO/NORMAL/TURBO) — RadioButton 을 토글 버튼 모양으로 -->
<Style x:Key="PresetRadio" TargetType="RadioButton">
<Setter Property="Cursor" Value="Hand"/>
<Setter Property="FontSize" Value="10"/>
<Setter Property="FontWeight" Value="SemiBold"/>
<Setter Property="Foreground" Value="{StaticResource TextSecondaryBrush}"/>
<Setter Property="Margin" Value="2,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border x:Name="border" Background="{StaticResource CardBgBrush}" CornerRadius="5"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1" Padding="10,4">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="border" Property="Background" Value="{StaticResource AccentBlueBrush}"/>
<Setter TargetName="border" Property="BorderBrush" Value="{StaticResource AccentBlueBrush}"/>
<Setter Property="Foreground" Value="White"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="border" Property="Opacity" Value="0.85"/>
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="border" Property="Opacity" Value="0.4"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModernTextBox" TargetType="TextBox">
<Setter Property="Background" Value="{StaticResource CardBgBrush}"/>
<Setter Property="Foreground" Value="{StaticResource TextPrimaryBrush}"/>
+11 -4
View File
@@ -53,10 +53,17 @@
Style="{StaticResource ModernButton}" Click="RefreshPorts_Click"
Background="{StaticResource CardBgBrush}" Margin="0,0,12,0" Padding="0"/>
<Button x:Name="btnAutoChange" Content="자동변경" Style="{StaticResource ModernButton}"
Background="{StaticResource AccentBlueBrush}" VerticalAlignment="Center"
Margin="0,0,12,0" Padding="14,7" FontSize="11" Click="AutoChange_Click"
ToolTip="거실→방1~3 순서로 30초마다 오염레벨 0→1→2→3→4 자동 변경"/>
<StackPanel Orientation="Vertical" VerticalAlignment="Center" Margin="0,0,12,0">
<Button x:Name="btnAutoChange" Content="센서값 자동 변경" Style="{StaticResource ModernButton}"
Background="{StaticResource AccentBlueBrush}"
Padding="14,6" FontSize="11" Click="AutoChange_Click"
ToolTip="선택한 프리셋모드(ECO/NORMAL/TURBO) 밴드로 거실→방1~3 순서로 30초마다 오염레벨 0→1→2→3→4 자동 변경"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,4,0,0">
<RadioButton x:Name="RbAutoEco" Content="ECO" GroupName="AutoPreset" Style="{StaticResource PresetRadio}"/>
<RadioButton x:Name="RbAutoNorm" Content="NORMAL" GroupName="AutoPreset" Style="{StaticResource PresetRadio}" IsChecked="True"/>
<RadioButton x:Name="RbAutoTurbo" Content="TURBO" GroupName="AutoPreset" Style="{StaticResource PresetRadio}"/>
</StackPanel>
</StackPanel>
<TextBlock Text="폴링(ms)" Foreground="{StaticResource TextPrimaryBrush}"
VerticalAlignment="Center" Margin="0,0,6,0" FontSize="11" FontWeight="SemiBold"/>
+44 -5
View File
@@ -24,6 +24,7 @@ namespace DiffuserSimulator
new() { Interval = TimeSpan.FromSeconds(30) };
private int _autoStep; // 0..19 (room = step/5, level = step%5)
private bool _autoRunning;
private int _autoPreset = 1; // 자동변경 시 적용할 프리셋모드 (0 ECO/1 NORMAL/2 TURBO, 기본 NORMAL)
private static readonly string[] RoomNames = { "거실", "방 1", "방 2", "방 3", "방 4" };
private static readonly Color[] RoomColors =
@@ -40,12 +41,12 @@ namespace DiffuserSimulator
// (힘펠은 PM10/VOC 임계가 99999 캡이라 Band 분류상 L4 도달 불가 → 4단계는 ECO/NORMAL/TURBO 용)
private static readonly int[][] PrePM25 = { new[]{10,30,50,75,95}, new[]{7,22,40,60,80}, new[]{6,18,31,45,60}, new[]{7,25,55,90,110} };
private static readonly int[][] PrePM10 = { new[]{20,63,106,150,185}, new[]{14,47,85,120,150}, new[]{12,39,66,91,115}, new[]{0,0,0,0,0} };
private static readonly int[][] PreCO2 = { new[]{500,1150,1450,1800,2100}, new[]{400,850,1150,1450,1700}, new[]{300,700,900,1100,1300}, new[]{350,850,1250,1750,1700} };
private static readonly int[][] PreCO2 = { new[]{500,1150,1450,1800,2100}, new[]{400,950,1250,1550,1850}, new[]{350,850,1150,1450,1750}, new[]{350,850,1250,1750,1700} };
private static readonly int[][] PreVOC = { new[]{85,183,252,370,460}, new[]{60,135,200,300,400}, new[]{52,112,156,228,290}, new[]{17,115,270,408,500} };
private static readonly int[][] PreTVOC = { new[]{50,250,700,1500,1800}, new[]{50,250,700,1500,1800}, new[]{50,250,700,1500,1800}, new[]{50,250,700,1500,1800} };
// 분류용 상한 임계 [프리셋][L1~L3] (그 이상 = 매우나쁨) — ECO/NORMAL/TURBO 는 ErvState 와 동일, 힘펠은 룸컨 사양
private static readonly int[][] ThrCO2 = { new[]{1000,1300,1600,2000}, new[]{700,1000,1300,1600}, new[]{600,800,1000,1200}, new[]{700,1000,1500,99999} };
private static readonly int[][] ThrCO2 = { new[]{1000,1300,1600,2000}, new[]{800,1100,1400,1700}, new[]{700,1000,1300,1600}, new[]{700,1000,1500,99999} };
private static readonly int[][] ThrPM25 = { new[]{20,38,60,86}, new[]{14,29,49,69}, new[]{12,23,38,52}, new[]{15,35,75,99999} };
private static readonly int[][] ThrPM10 = { new[]{40,86,126,173}, new[]{28,66,102,138}, new[]{24,53,78,104}, new[]{99999,99999,99999,99999} };
private static readonly int[][] ThrVOC = { new[]{171,195,308,438}, new[]{120,150,250,350}, new[]{103,120,192,263}, new[]{99999,99999,99999,99999} };
@@ -75,6 +76,12 @@ namespace DiffuserSimulator
BuildRoomPanels();
RefreshPorts();
ApplySlaveUi(); // 슬레이브 전용 UI 상태(각도 readonly 등)
// 자동변경 프리셋모드 선택 버튼 (ECO/NORMAL/TURBO)
RbAutoEco.Checked += (s, e) => SetAutoPreset(0);
RbAutoNorm.Checked += (s, e) => SetAutoPreset(1);
RbAutoTurbo.Checked += (s, e) => SetAutoPreset(2);
_autoTimer.Tick += AutoTick;
Closed += (_, _) => { _autoTimer.Stop(); _slave.Dispose(); };
}
@@ -327,6 +334,14 @@ namespace DiffuserSimulator
_ui[i].RbTurbo.IsEnabled = !himpel;
}
// 자동변경 프리셋모드 선택 버튼 : DL=활성 / 힘펠=비활성
if (RbAutoEco != null)
{
RbAutoEco.IsEnabled = !himpel;
RbAutoNorm.IsEnabled = !himpel;
RbAutoTurbo.IsEnabled = !himpel;
}
// LED 디밍 : DL=활성 / 힘펠=비활성 — 거실(0)·방1~3(1~3)
for (int i = 0; i < 4; i++) SetLedDimming(i, enabled: !himpel);
@@ -598,22 +613,46 @@ namespace DiffuserSimulator
{
_autoTimer.Stop();
_autoRunning = false;
btnAutoChange.Content = "자동변경";
btnAutoChange.Content = "센서값 자동 변경";
OnLog("[자동변경] 중지");
return;
}
// 거실~방3(0~3) 활성화 (이미 켜져 있으면 무시) 후 전체 0(좋음)에서 시작
// 거실~방3(0~3) 활성화 (이미 켜져 있으면 무시) 후 선택 프리셋모드 밴드의 전체 0(좋음)에서 시작
for (int i = 0; i <= 3; i++)
if (_ui[i].ChkEnabled.IsChecked != true) _ui[i].ChkEnabled.IsChecked = true;
ApplyAutoPresetToRooms(); // 선택한 ECO/NORMAL/TURBO 밴드 적용
for (int r = 0; r <= 3; r++) ApplyPreset(r, 0);
_autoStep = 0;
_autoRunning = true;
btnAutoChange.Content = "자동 변경 중지";
OnLog("[자동변경] 시작 — 전체 0에서 30초 대기 후 방1→방2→방3→거실 순 누적(0→4)");
OnLog($"[자동변경] 시작({AutoPresetName(_autoPreset)}) — 전체 0에서 30초 대기 후 방1→방2→방3→거실 순 누적(0→4)");
_autoTimer.Start(); // 즉시 적용하지 않음 → 초기 0 0 0 0 을 30초 유지 후 첫 변경
}
private static string AutoPresetName(int p) => p == 0 ? "ECO" : p == 2 ? "TURBO" : "NORMAL";
// 자동변경 프리셋모드 선택 → 실행 중이면 즉시 현재 방들에 새 밴드 재적용
private void SetAutoPreset(int preset)
{
_autoPreset = preset;
if (_autoRunning) ApplyAutoPresetToRooms();
}
// 선택한 자동변경 프리셋모드를 거실~방3(0~3) 패널에 반영 → 각 방의 센서 밴드(_roomPreset) 갱신
private void ApplyAutoPresetToRooms()
{
for (int i = 0; i <= 3; i++)
{
switch (_autoPreset)
{
case 0: _ui[i].RbEco.IsChecked = true; break;
case 1: _ui[i].RbNorm.IsChecked = true; break;
case 2: _ui[i].RbTurbo.IsChecked = true; break;
}
}
}
// 레벨 스윕(누적) : 매 30초 한 방씩 현재 레벨로 올림(방1→방2→방3→거실).
// 한 바퀴(4방) 다 올리면 레벨+1. 앞서 올린 방은 값 유지(누적). 전체 4 도달 후 0으로 리셋 반복.
private static readonly int[] AutoOrder = { 1, 2, 3, 0 }; // 방1, 방2, 방3, 거실
+20 -6
View File
@@ -162,6 +162,8 @@ namespace DiffuserSimulator
}
if (totalRead < 29) continue;
// CRC 바이트순서 = lo-first(표준 리틀엔디안). 펌웨어 CRC16()이 표준MODBUS의
// 바이트스왑값을 반환 + [27]=icrc>>8 배치 → 두 스왑 상쇄 → 와이어는 [27]=하위,[28]=상위.
ushort rxCrc = (ushort)(rxBuf[27] | (rxBuf[28] << 8));
ushort calcCrc = CalcCRC16(rxBuf, 27);
if (rxCrc != calcCrc) { Log($"[CRC오류] 수신:0x{rxCrc:X4} 계산:0x{calcCrc:X4}"); continue; }
@@ -192,12 +194,22 @@ namespace DiffuserSimulator
continue;
}
// Option B 패킷 구분 (250624 dump 패턴 일치):
// byte 5 = 0x01 → 명령 (Power ON, state 적용)
// byte 5 = 0x00 → 폴링 (상태 조회만, state 무변경)
// 폴링에서 byte 10/11/8 = 0 을 그대로 적용하면 댐퍼/LED 가 0 으로 reset 됨.
// 패킷 구분 : byte5 = Power. 하위비트 = 전원(0/1), 상위 0x80 = Control Cmd (dump.txt 스펙).
// 전원 OFF(하위비트 0) : 펌웨어가 댐퍼=0·LED=0 을 보냄 → 디퓨저 닫힘·소등 (전원우선)
// 전원 ON : 폴링/명령 모두 byte5 하위비트=1 → 댐퍼/LED 상태 적용
// (과거 isCommand=byte5!=0 만 적용 → 전원 OFF(byte5=0) 닫힘명령을 폴링으로 오인,
// 댐퍼 열림·LED 켜진 채 남던 문제 수정)
bool powerOff = ((rxBuf[5] & 0x7F) == 0x00);
bool isCommand = (rxBuf[5] != 0x00);
if (isCommand)
if (powerOff)
{
// 전원 OFF → 급기/배기 댐퍼 닫힘 + LED 소등 (수동닫기/수동LED 와 무관, 전원이 우선)
room.Power = 0;
room.DamperAngleSA = 0;
room.DamperAngleEA = 0;
room.LedBrightness = 0;
}
else if (isCommand)
{
// 마스터 명령 적용 — ID1 별로 해당 type 의 필드만 갱신.
// ID1=0x01 (SA): damper SA 만
@@ -347,6 +359,7 @@ namespace DiffuserSimulator
p[11] = room.DamperAngleEA;
// byte 12~26: 0 (RPM / Reset / 예약 등 미사용)
ushort crc = CalcCRC16(p, 27);
// lo-first (표준 리틀엔디안) — 와이어 [27]=하위, [28]=상위
p[27] = (byte)(crc & 0xFF);
p[28] = (byte)((crc >> 8) & 0xFF);
return p;
@@ -378,7 +391,7 @@ namespace DiffuserSimulator
if (total < 39) return null;
if (buf[1] != 0x01) continue; // not slave
ushort rxCrc = (ushort)(buf[37] | (buf[38] << 8));
ushort rxCrc = (ushort)(buf[37] | (buf[38] << 8)); // lo-first (표준 리틀엔디안)
ushort calc = CalcCRC16(buf, 37);
if (rxCrc != calc) { Log($"[CRC오류] 수신:0x{rxCrc:X4} 계산:0x{calc:X4}"); return null; }
return buf;
@@ -402,6 +415,7 @@ namespace DiffuserSimulator
p[33] = (byte)((room.ErrorCode >> 8) & 0xFF); p[34] = (byte)(room.ErrorCode & 0xFF);
p[35] = room.VersionMajor; p[36] = room.VersionMinor;
ushort crc = CalcCRC16(p, 37);
// lo-first : 펌웨어 RX가 (Rx[37]<<8)|Rx[38] 로 읽고 CRC16()=스왑값과 비교 → lo-first로 보내야 일치
p[37] = (byte)(crc & 0xFF); p[38] = (byte)((crc >> 8) & 0xFF);
return p;
}
@@ -65,6 +65,7 @@ namespace ERVSimulator.Protocol
p[10] = (byte)rm.CurrentSA;
p[11] = (byte)rm.CurrentRA;
ushort crc = Crc16.Modbus(p, 0, 27);
// lo-first : 펌웨어 CRC16()이 표준MODBUS 바이트스왑값 반환 + [27]=icrc>>8 배치 → 와이어는 리틀엔디안
p[27] = (byte)(crc & 0xFF);
p[28] = (byte)(crc >> 8);
_ch.Send(p, 29);
@@ -100,7 +101,7 @@ namespace ERVSimulator.Protocol
void HandleResponse(byte[] p)
{
ushort rxcrc = (ushort)(p[37] | (p[38] << 8));
ushort rxcrc = (ushort)(p[37] | (p[38] << 8)); // lo-first (표준 리틀엔디안)
if (Crc16.Modbus(p, 0, 37) != rxcrc)
{
PacketReceived?.Invoke($"Diff RX CRC오류 {HexFormat.Bytes(p, 39)}");
+11 -11
View File
@@ -12,11 +12,11 @@ namespace HoodSimulator
readonly HoodProtocol _hood = new();
int _rxCount;
// 조리 종료 후 메이크업 유지(잔여 냄새 배출) — 후드측이 담당. 유지중에는 ERV 에 계속 '켜짐' 보고,
// 조리 종료 후 지연배기(잔여 냄새 배출) — 후드측이 담당. 배기중에는 ERV 에 계속 '켜짐' 보고,
// 종료 시점에 OFF 전송 → ERV 가 원래 모드/풍량으로 복귀. (사양 260613 9p 3.3)
readonly System.Windows.Threading.DispatcherTimer _makeupTimer =
new() { Interval = TimeSpan.FromSeconds(1) };
const int MakeupHoldSec = 10; // 메이크업 유지 시간 (10초)
const int MakeupHoldSec = 10; // 지연배기 유지 시간 — 시간 불변(시뮬 10초; 사양 원래 30초)
int _makeupRemainSec;
static readonly Brush AccentCyan = (Brush)new BrushConverter().ConvertFromString("#7DCFFF")!;
@@ -83,7 +83,7 @@ namespace HoodSimulator
{
if (tglPower.IsChecked == true)
{
// 켜기 : 진행중인 메이크업 유지 취소 후 즉시 ON (풍량 1)
// 켜기 : 진행중인 지연배기 취소 후 즉시 ON (풍량 1)
StopMakeupHold();
_hood.PowerOn = true;
_hood.FanStage = 1;
@@ -94,27 +94,27 @@ namespace HoodSimulator
}
else
{
// 끄기 : OFF 표시 + 옆에 메이크업 유지(1분) 카운트다운 시작. 그동안 ERV엔 계속 '켜짐' 보고.
// 지 종료 시 후드 OFF 전송 → ERV 가 원래 모드/풍량으로 복귀.
// 끄기 : OFF 표시 + 옆에 지연배기 카운트다운 시작. 그동안 ERV엔 계속 '켜짐' 보고.
// 지연배기 종료 시 후드 OFF 전송 → ERV 가 원래 모드/풍량으로 복귀.
txtPower.Text = "OFF";
txtPower.Foreground = TextSecondary;
if (_hood.PowerOn && _makeupRemainSec == 0)
{
_makeupRemainSec = MakeupHoldSec;
_makeupTimer.Start();
txtMakeup.Text = $"메이크업 {_makeupRemainSec}s";
OnLog($"[제어] 전원 OFF 요청 → 메이크업 에어 {MakeupHoldSec}s 유지 (ERV엔 계속 켜짐 보고)");
txtMakeup.Text = $"지연배기(원래는 30초) {_makeupRemainSec}s";
OnLog($"[제어] 전원 OFF 요청 → 지연배기 {MakeupHoldSec}s 유지 (ERV엔 계속 켜짐 보고)");
}
}
}
// 메이크업 유지 카운트다운 (1초). 0이 되면 실제 OFF 전송.
// 지연배기 카운트다운 (1초). 0이 되면 실제 OFF 전송.
void MakeupTick(object? s, EventArgs e)
{
_makeupRemainSec--;
if (_makeupRemainSec > 0)
{
txtMakeup.Text = $"메이크업 {_makeupRemainSec}s";
txtMakeup.Text = $"지연배기(원래는 30초) {_makeupRemainSec}s";
}
else
{
@@ -122,7 +122,7 @@ namespace HoodSimulator
_hood.PowerOn = false;
_hood.FanStage = 0;
UpdateFanButtons();
OnLog("[제어] 메이크업 유지 종료 → 후드 OFF 전송 (ERV 원래 모드/풍량 복귀)");
OnLog("[제어] 지연배기 종료 → 후드 OFF 전송 (ERV 원래 모드/풍량 복귀)");
}
}
@@ -166,7 +166,7 @@ namespace HoodSimulator
// 에러 발생 시 전원 OFF / 풍량 0 / 조명 OFF (다음 응답에 반영되어 전송)
if (_hood.ErrorCode != 0)
{
StopMakeupHold(); // 진행중인 메이크업 유지 즉시 취소
StopMakeupHold(); // 진행중인 지연배기 즉시 취소
_hood.PowerOn = false;
_hood.FanStage = 0;
_hood.Light = false;
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\C3.ewp</path>
</project>
<batchBuild/>
</workspace>
@@ -0,0 +1,40 @@
@REM This batch file has been generated by the IAR Embedded Workbench
@REM C-SPY Debugger, as an aid to preparing a command line for running
@REM the cspybat command line utility using the appropriate settings.
@REM
@REM Note that this file is generated every time a new debug session
@REM is initialized, so you may want to move or rename the file before
@REM making changes.
@REM
@REM You can launch cspybat by typing the name of this batch file followed
@REM by the name of the debug file (usually an ELF/DWARF or UBROF file).
@REM
@REM Read about available command line parameters in the C-SPY Debugging
@REM Guide. Hints about additional command line parameters that may be
@REM useful in specific cases:
@REM --download_only Downloads a code image without starting a debug
@REM session afterwards.
@REM --silent Omits the sign-on message.
@REM --timeout Limits the maximum allowed execution time.
@REM
@echo off
if not "%~1" == "" goto debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5_2\common\bin\cspybat" -f "D:\0. Project_internal\3. Himpel_2Team\13. 각실제어시스템(Each_Room_Control)\4. FND_display\IAR\settings\C3.Release.general.xcl" --backend -f "D:\0. Project_internal\3. Himpel_2Team\13. 각실제어시스템(Each_Room_Control)\4. FND_display\IAR\settings\C3.Release.driver.xcl"
@echo off
goto end
:debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5_2\common\bin\cspybat" -f "D:\0. Project_internal\3. Himpel_2Team\13. 각실제어시스템(Each_Room_Control)\4. FND_display\IAR\settings\C3.Release.general.xcl" "--debug_file=%~1" --backend -f "D:\0. Project_internal\3. Himpel_2Team\13. 각실제어시스템(Each_Room_Control)\4. FND_display\IAR\settings\C3.Release.driver.xcl"
@echo off
:end
@@ -0,0 +1,17 @@
"--endian=little"
"--cpu=Cortex-M0"
"--fpu=None"
"-p"
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5_2\arm\CONFIG\debugger\Nuvoton\NANO100SE3BN.ddf"
"--semihosting=none"
"--device=NANO100SE3BN"
@@ -0,0 +1,13 @@
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5_2\arm\bin\armproc.dll"
"C:\Program Files (x86)\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll"
"D:\0. Project_internal\3. Himpel_2Team\13. °¢½ÇÁ¦¾î½Ã½ºÅÛ(Each_Room_Control)\4. FND_display\IAR\Release\Exe\LCD_Pixel_OnOff_Test.out"
--plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5_2\arm\bin\armbat.dll"
--flash_loader "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5_2\arm\config\flashloader\Nuvoton\FlashNano100.board"
+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<crun>
<version>1</version>
<filter_entries>
<filter index="0" type="default">
<type>*</type>
<start_file>*</start_file>
<end_file>*</end_file>
<action_debugger>0</action_debugger>
<action_log>1</action_log>
</filter>
</filter_entries>
</crun>
+141
View File
@@ -0,0 +1,141 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Project>
<Desktop>
<Static>
<Debug-Log>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>1306</ColumnWidth1></Debug-Log>
<Build>
<ColumnWidth0>20</ColumnWidth0>
<ColumnWidth1>979</ColumnWidth1>
<ColumnWidth2>261</ColumnWidth2>
<ColumnWidth3>65</ColumnWidth3>
</Build>
<Workspace>
<ColumnWidths>
<Column0>226</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>
</Workspace>
<Disassembly>
<col-names>
<item>Disassembly</item><item>_I0</item></col-names>
<col-widths>
<item>500</item><item>20</item></col-widths>
<DisasmHistory/>
<PreferedWindows>
<Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows>
<ShowCodeCoverage>1</ShowCodeCoverage><ShowInstrProfiling>1</ShowInstrProfiling></Disassembly>
<StaticWatch>
<expressions>
<item>Rx_FND_buff</item><item>SEN66_CO2_value</item><item>Power_On</item><item></item></expressions>
<col-names>
<item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names>
<col-widths>
<item>190</item><item>150</item><item>100</item><item>225</item></col-widths>
</StaticWatch>
<Find-in-Files>
<ColumnWidth0>569</ColumnWidth0><ColumnWidth1>94</ColumnWidth1><ColumnWidth2>854</ColumnWidth2><ColumnWidth3>379</ColumnWidth3></Find-in-Files>
<Select-Ambiguous-Definitions><ColumnWidth0>664</ColumnWidth0><ColumnWidth1>94</ColumnWidth1><ColumnWidth2>1138</ColumnWidth2></Select-Ambiguous-Definitions><Find-All-References><ColumnWidth0>664</ColumnWidth0><ColumnWidth1>94</ColumnWidth1><ColumnWidth2>1138</ColumnWidth2></Find-All-References></Static>
<Windows>
<Wnd1>
<Tabs>
<Tab>
<Identity>TabID-9736-5620</Identity>
<TabName>Debug Log</TabName>
<Factory>Debug-Log</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-9213-5630</Identity>
<TabName>Build</TabName>
<Factory>Build</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-16010-10620</Identity>
<TabName>Find in Files</TabName>
<Factory>Find-in-Files</Factory>
<Session/>
</Tab>
<Tab><Identity>TabID-26548-18901</Identity><TabName>Ambiguous Definitions</TabName><Factory>Select-Ambiguous-Definitions</Factory><Session/></Tab><Tab><Identity>TabID-20280-16953</Identity><TabName>References</TabName><Factory>Find-All-References</Factory><Session/></Tab></Tabs>
<SelectedTab>2</SelectedTab></Wnd1><Wnd2>
<Tabs>
<Tab>
<Identity>TabID-20484-5624</Identity>
<TabName>Workspace</TabName>
<Factory>Workspace</Factory>
<Session>
<NodeDict><ExpandedNode>C3</ExpandedNode><ExpandedNode>C3/Libraries</ExpandedNode><ExpandedNode>C3/User</ExpandedNode><ExpandedNode>C3/User/samsungSDS.c</ExpandedNode></NodeDict></Session>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd2><Wnd6>
<Tabs>
<Tab>
<Identity>TabID-25357-10035</Identity>
<TabName>Live Watch</TabName>
<Factory>StaticWatch</Factory>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd6><Wnd7><Tabs><Tab><Identity>TabID-13213-8013</Identity><TabName>Disassembly</TabName><Factory>Disassembly</Factory><Session/></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd7></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_system.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>364</YPos2><SelStart2>11208</SelStart2><SelEnd2>11208</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>20</YPos2><SelStart2>1021</SelStart2><SelEnd2>1021</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_Uart.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>300</YPos2><SelStart2>8602</SelStart2><SelEnd2>8602</SelEnd2></Tab><ActiveTab>2</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\mc2002.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>336</YPos2><SelStart2>5655</SelStart2><SelEnd2>5663</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-04FE8D60><key>iaridepm.enu1</key></Toolbar-04FE8D60><Toolbar-0D1CC9A0><key>debuggergui.enu1</key></Toolbar-0D1CC9A0></Sizes></Row0><Row1><Sizes/></Row1></Top><Left><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>739</Bottom><Right>300</Right><x>-2</x><y>-2</y><xscreen>299</xscreen><yscreen>279</yscreen><sizeHorzCX>145996</sizeHorzCX><sizeHorzCY>262959</sizeHorzCY><sizeVertCX>147461</sizeVertCX><sizeVertCY>698398</sizeVertCY></Rect></Wnd2></Sizes></Row0></Left><Right><Row0><Sizes><Wnd6><Rect><Top>-2</Top><Left>-2</Left><Bottom>739</Bottom><Right>414</Right><x>-2</x><y>-2</y><xscreen>214</xscreen><yscreen>211</yscreen><sizeHorzCX>104492</sizeHorzCX><sizeHorzCY>198869</sizeHorzCY><sizeVertCX>203125</sizeVertCX><sizeVertCY>698398</sizeVertCY></Rect></Wnd6></Sizes></Row0><Row1><Sizes><Wnd7><Rect><Top>-2</Top><Left>412</Left><Bottom>739</Bottom><Right>625</Right><x>412</x><y>-2</y><xscreen>213</xscreen><yscreen>215</yscreen><sizeHorzCX>104004</sizeHorzCX><sizeHorzCY>202639</sizeHorzCY><sizeVertCX>104004</sizeVertCX><sizeVertCY>698398</sizeVertCY></Rect></Wnd7></Sizes></Row1></Right><Bottom><Row0><Sizes><Wnd1><Rect><Top>-2</Top><Left>-2</Left><Bottom>277</Bottom><Right>2050</Right><x>-2</x><y>-2</y><xscreen>2052</xscreen><yscreen>279</yscreen><sizeHorzCX>1001953</sizeHorzCX><sizeHorzCY>262959</sizeHorzCY><sizeVertCX>145996</sizeVertCX><sizeVertCY>262959</sizeVertCY></Rect></Wnd1></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Project>
+101
View File
@@ -0,0 +1,101 @@
[Stack]
FillEnabled=0
OverflowWarningsEnabled=1
WarningThreshold=90
SpWarningsEnabled=1
WarnLogOnly=1
UseTrigger=1
TriggerName=main
LimitSize=0
ByteLimit=50
[DebugChecksum]
Checksum=1551100862
[CodeCoverage]
Enabled=_ 0
[Exceptions]
StopOnUncaught=_ 0
StopOnThrow=_ 0
[CallStack]
ShowArgs=0
[Disassembly]
MixedMode=1
[DriverProfiling]
Enabled=0
Mode=1
Graph=0
Symbiont=0
Exclusions=
[CallStackLog]
Enabled=0
[CallStackStripe]
ShowTiming=1
[InterruptLog]
LogEnabled=0
GraphEnabled=0
ShowTimeLog=1
SumEnabled=0
ShowTimeSum=1
SumSortOrder=0
[DataLog]
LogEnabled=0
GraphEnabled=0
ShowTimeLog=1
SumEnabled=0
ShowTimeSum=1
[Breakpoints2]
Count=0
[Interrupts]
Enabled=1
[MemConfig]
Base=1
Manual=0
Ddf=1
TypeViol=0
Stop=1
[Trace1]
Enabled=0
ShowSource=1
[Simulator]
Freq=10000000
MultiCoreRunAll=1
[array_types]
Fmt0=uint8_t[20] 4 0
Fmt1=uint8_t[25] 4 0
Fmt2=uint8_t[30] 4 0
Fmt3=uint8_t[40] 4 0
Fmt4=uint8_t[50] 4 0
[watch_formats]
Fmt0={W}42:CO2_Value 3 0
Fmt1={W}42:Command_request_type 4 0
Fmt2={W}42:Err_Code 4 0
Fmt3={W}42:Fan1_Speed 3 0
Fmt4={W}42:Fan2_Speed 3 0
Fmt5={W}42:ID_buf 4 0
Fmt6={W}42:InCom_Packet_Length 3 0
Fmt7={W}42:InCom_Rx_Pos 3 0
Fmt8={W}42:Min_Count 3 0
Fmt9={W}42:Packet_Type 4 0
Fmt10={W}42:SA485_Rx_Pos 3 0
Fmt11={W}42:Test_Fan1_Ven_1_dan 3 0
Fmt12={W}42:roomcon_com_count 3 0
Fmt13={W}42:test_num 4 0
[Log file]
LoggingEnabled=_ 0
LogFile=_ ""
Category=_ 0
[TermIOLog]
LoggingEnabled=_ 0
LogFile=_ ""
[Disassemble mode]
mode=0
[Breakpoints]
Count=0
[Aliases]
A0=_ "D:\kang\1. work\2024\Library\CMSIS\Include\core_cm0.h" ""
A1=_ "D:\kang\1. work\2024\Library\StdDriver\inc\sys.h" ""
A2=_ "D:\kang\1. work\2024\Library\StdDriver\src\EEPROM_Emulate.c" "D:\kang\1.work\2024\Library\StdDriver\src\EEPROM_Emulate.c"
A3=_ "D:\kang\1. work\2024\Library\StdDriver\src\fmc.c" ""
A4=_ "D:\kang\1. work\2024\Library\StdDriver\src\gpio.c" ""
A5=_ "D:\kang\1. work\2024\each room\1. BunBaeGi\main.c" ""
Count=6
SuppressDialog=0
+88
View File
@@ -0,0 +1,88 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Workspace>
<ConfigDictionary>
<CurrentConfigs><Project>C3/Release</Project></CurrentConfigs></ConfigDictionary>
<Desktop>
<Static>
<Workspace>
<ColumnWidths>
<Column0>155</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>
</Workspace>
<Debug-Log>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>1306</ColumnWidth1></Debug-Log>
<Build>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>979</ColumnWidth1><ColumnWidth2>261</ColumnWidth2><ColumnWidth3>65</ColumnWidth3></Build>
<Find-in-Files>
<ColumnWidth0>404</ColumnWidth0><ColumnWidth1>67</ColumnWidth1><ColumnWidth2>606</ColumnWidth2><ColumnWidth3>269</ColumnWidth3></Find-in-Files>
<TerminalIO/><Find-All-Declarations><ColumnWidth0>709</ColumnWidth0><ColumnWidth1>101</ColumnWidth1><ColumnWidth2>1215</ColumnWidth2></Find-All-Declarations><Find-All-References><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows><Window><Factory>Debug-Log</Factory></Window><Window><Factory>Build</Factory></Window><Window><Factory>Find-in-Files</Factory></Window><Window><Factory>Find-All-Declarations</Factory></Window></Windows></PreferedWindows><ColumnWidth0>664</ColumnWidth0><ColumnWidth1>94</ColumnWidth1><ColumnWidth2>1138</ColumnWidth2></Find-All-References><PROJECT_GUI_CALL_GRAPH><PreferedWindows><Position>3</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><col-names><item>File</item><item>Function</item><item>Line</item></col-names><col-widths><item>200</item><item>700</item><item>100</item></col-widths></PROJECT_GUI_CALL_GRAPH></Static>
<Windows>
<Wnd0>
<Tabs>
<Tab>
<Identity>TabID-15914-11067</Identity>
<TabName>Workspace</TabName>
<Factory>Workspace</Factory>
<Session>
<NodeDict><ExpandedNode>C3</ExpandedNode><ExpandedNode>C3/CMSIS</ExpandedNode><ExpandedNode>C3/Libraries</ExpandedNode><ExpandedNode>C3/User</ExpandedNode><ExpandedNode>C3/User/CV_net.c</ExpandedNode><ExpandedNode>C3/User/main.c</ExpandedNode></NodeDict></Session>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd0><Wnd1>
<Tabs>
<Tab>
<Identity>TabID-21957-11159</Identity>
<TabName>Debug Log</TabName>
<Factory>Debug-Log</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-1046-11551</Identity>
<TabName>Build</TabName>
<Factory>Build</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-32309-11988</Identity>
<TabName>Find in Files</TabName>
<Factory>Find-in-Files</Factory>
<Session/>
</Tab>
<Tab><Identity>TabID-29222-17695</Identity><TabName>Declarations</TabName><Factory>Find-All-Declarations</Factory><Session/></Tab><Tab><Identity>TabID-5512-18079</Identity><TabName>References</TabName><Factory>Find-All-References</Factory><Session/></Tab></Tabs>
<SelectedTab>1</SelectedTab></Wnd1></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_system.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>364</YPos2><SelStart2>11208</SelStart2><SelEnd2>11208</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>20</YPos2><SelStart2>1021</SelStart2><SelEnd2>1021</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_Uart.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>295</YPos2><SelStart2>8602</SelStart2><SelEnd2>8602</SelEnd2></Tab><ActiveTab>2</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\mc2002.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>336</YPos2><SelStart2>5655</SelStart2><SelEnd2>5663</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Pane/><Sizes><Pane><X>732967</X><Y>1000000</Y></Pane><Pane><X>267032</X><Y>1000000</Y></Pane></Sizes><SplitMode>4</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-04FE8D60><key>iaridepm.enu1</key></Toolbar-04FE8D60></Sizes></Row0><Row1><Sizes/></Row1><Row2><Sizes/></Row2></Top><Left><Row0><Sizes><Wnd0><Rect><Top>-2</Top><Left>-2</Left><Bottom>803</Bottom><Right>246</Right><x>-2</x><y>-2</y><xscreen>24</xscreen><yscreen>45</yscreen><sizeHorzCX>11719</sizeHorzCX><sizeHorzCY>42413</sizeHorzCY><sizeVertCX>121094</sizeVertCX><sizeVertCY>758718</sizeVertCY></Rect></Wnd0></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd1><Rect><Top>-2</Top><Left>-2</Left><Bottom>213</Bottom><Right>2050</Right><x>-2</x><y>-2</y><xscreen>2052</xscreen><yscreen>215</yscreen><sizeHorzCX>1001953</sizeHorzCX><sizeHorzCY>202639</sizeHorzCY><sizeVertCX>11719</sizeVertCX><sizeVertCY>42413</sizeVertCY></Rect></Wnd1></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Workspace>
+2
View File
@@ -0,0 +1,2 @@
[MainWindow]
WindowPlacement=_ 2068 148 3791 1183 3
@@ -0,0 +1,40 @@
@REM This batch file has been generated by the IAR Embedded Workbench
@REM C-SPY Debugger, as an aid to preparing a command line for running
@REM the cspybat command line utility using the appropriate settings.
@REM
@REM Note that this file is generated every time a new debug session
@REM is initialized, so you may want to move or rename the file before
@REM making changes.
@REM
@REM You can launch cspybat by typing the name of this batch file followed
@REM by the name of the debug file (usually an ELF/DWARF or UBROF file).
@REM
@REM Read about available command line parameters in the C-SPY Debugging
@REM Guide. Hints about additional command line parameters that may be
@REM useful in specific cases:
@REM --download_only Downloads a code image without starting a debug
@REM session afterwards.
@REM --silent Omits the sign-on message.
@REM --timeout Limits the maximum allowed execution time.
@REM
@echo off
if not "%~1" == "" goto debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\102. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\SampleCode\StdDriver\LCD_Pixel_OnOff_Test\IAR\settings\LCD_Pixel_OnOff_Test.Release.general.xcl" --backend -f "D:\0. Project_internal\102. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\SampleCode\StdDriver\LCD_Pixel_OnOff_Test\IAR\settings\LCD_Pixel_OnOff_Test.Release.driver.xcl"
@echo off
goto end
:debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\102. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\SampleCode\StdDriver\LCD_Pixel_OnOff_Test\IAR\settings\LCD_Pixel_OnOff_Test.Release.general.xcl" "--debug_file=%~1" --backend -f "D:\0. Project_internal\102. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\SampleCode\StdDriver\LCD_Pixel_OnOff_Test\IAR\settings\LCD_Pixel_OnOff_Test.Release.driver.xcl"
@echo off
:end
@@ -0,0 +1,19 @@
"--endian=little"
"--cpu=Cortex-M0"
"--fpu=None"
"-p"
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\CONFIG\debugger\Nuvoton\ionano100bn.ddf"
"--drv_verify_download"
"--semihosting=none"
"--device=Nano100"
@@ -0,0 +1,13 @@
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armproc.dll"
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\..\..\..\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll"
"D:\0. Project_internal\102. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\SampleCode\StdDriver\LCD_Pixel_OnOff_Test\IAR\Release\Exe\LCD_Pixel_OnOff_Test.out"
--plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armbat.dll"
--flash_loader "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\config\flashloader\Nuvoton\Nano100_APROM.board"
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<crun>
<version>1</version>
<filter_entries>
<filter index="0" type="default">
<type>*</type>
<start_file>*</start_file>
<end_file>*</end_file>
<action_debugger>0</action_debugger>
<action_log>1</action_log>
</filter>
</filter_entries>
</crun>
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Project/>
@@ -0,0 +1,17 @@
[Stack]
FillEnabled=0
OverflowWarningsEnabled=1
WarningThreshold=90
SpWarningsEnabled=1
WarnLogOnly=1
UseTrigger=1
TriggerName=main
LimitSize=0
ByteLimit=50
[Disassemble mode]
mode=0
[Breakpoints]
Count=0
[Aliases]
Count=0
SuppressDialog=0
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Workspace>
<ConfigDictionary>
<CurrentConfigs><Project>LCD_Pixel_OnOff_Test/Release</Project></CurrentConfigs></ConfigDictionary>
<Desktop>
<Static>
<Debug-Log>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>1857</ColumnWidth1></Debug-Log>
<Workspace>
<ColumnWidths>
<Column0>298</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>
</Workspace>
<Find-in-Files>
<ColumnWidth0>569</ColumnWidth0><ColumnWidth1>94</ColumnWidth1><ColumnWidth2>854</ColumnWidth2><ColumnWidth3>379</ColumnWidth3></Find-in-Files>
</Static>
<Windows>
<Wnd2>
<Tabs>
<Tab>
<Identity>TabID-6185-3503</Identity>
<TabName>Workspace</TabName>
<Factory>Workspace</Factory>
<Session>
<NodeDict><ExpandedNode>LCD_Pixel_OnOff_Test</ExpandedNode><ExpandedNode>LCD_Pixel_OnOff_Test/Libraries</ExpandedNode><ExpandedNode>LCD_Pixel_OnOff_Test/User</ExpandedNode></NodeDict></Session>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd2><Wnd3>
<Tabs>
<Tab>
<Identity>TabID-16933-3506</Identity>
<TabName>Debug Log</TabName>
<Factory>Debug-Log</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-24608-3977</Identity>
<TabName>Find in Files</TabName>
<Factory>Find-in-Files</Factory>
<Session/>
</Tab>
</Tabs>
<SelectedTab>1</SelectedTab></Wnd3></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>225</YPos2><SelStart2>8095</SelStart2><SelEnd2>8107</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\LCDLib\Source\LCDLIB.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>210</YPos2><SelStart2>5833</SelStart2><SelEnd2>5833</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\inc\lcd.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>58</YPos2><SelStart2>3806</SelStart2><SelEnd2>3806</SelEnd2></Tab><ActiveTab>2</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\src\lcd.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>269</YPos2><SelStart2>7602</SelStart2><SelEnd2>7602</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\Device\Nuvoton\Nano100Series\Source\system_Nano100Series.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>99</YPos2><SelStart2>3538</SelStart2><SelEnd2>3538</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\src\retarget.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>33</YPos2><SelStart2>1833</SelStart2><SelEnd2>1833</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-010DD108><key>iaridepm.enu1</key></Toolbar-010DD108></Sizes></Row0></Top><Left><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>642</Bottom><Right>372</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>104167</sizeHorzCX><sizeHorzCY>194553</sizeHorzCY><sizeVertCX>194792</sizeVertCX><sizeVertCY>626459</sizeVertCY></Rect></Wnd2></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd3><Rect><Top>-2</Top><Left>-2</Left><Bottom>338</Bottom><Right>1922</Right><x>-2</x><y>-2</y><xscreen>1924</xscreen><yscreen>340</yscreen><sizeHorzCX>1002083</sizeHorzCX><sizeHorzCY>330739</sizeHorzCY><sizeVertCX>104167</sizeVertCX><sizeVertCY>194553</sizeVertCY></Rect></Wnd3></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Workspace>
@@ -0,0 +1,2 @@
[MainWindow]
WindowPlacement=_ 2109 266 3496 1121 3
@@ -0,0 +1,40 @@
@REM This batch file has been generated by the IAR Embedded Workbench
@REM C-SPY Debugger, as an aid to preparing a command line for running
@REM the cspybat command line utility using the appropriate settings.
@REM
@REM Note that this file is generated every time a new debug session
@REM is initialized, so you may want to move or rename the file before
@REM making changes.
@REM
@REM You can launch cspybat by typing the name of this batch file followed
@REM by the name of the debug file (usually an ELF/DWARF or UBROF file).
@REM
@REM Read about available command line parameters in the C-SPY Debugging
@REM Guide. Hints about additional command line parameters that may be
@REM useful in specific cases:
@REM --download_only Downloads a code image without starting a debug
@REM session afterwards.
@REM --silent Omits the sign-on message.
@REM --timeout Limits the maximum allowed execution time.
@REM
@echo off
if not "%~1" == "" goto debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\2. Himpel\3. R_remocon\0. firmware\1. Nuvoton_R_remocon\1. V1_0\IAR\settings\r_remocon.Release.general.xcl" --backend -f "D:\0. Project_internal\2. Himpel\3. R_remocon\0. firmware\1. Nuvoton_R_remocon\1. V1_0\IAR\settings\r_remocon.Release.driver.xcl"
@echo off
goto end
:debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\2. Himpel\3. R_remocon\0. firmware\1. Nuvoton_R_remocon\1. V1_0\IAR\settings\r_remocon.Release.general.xcl" "--debug_file=%~1" --backend -f "D:\0. Project_internal\2. Himpel\3. R_remocon\0. firmware\1. Nuvoton_R_remocon\1. V1_0\IAR\settings\r_remocon.Release.driver.xcl"
@echo off
:end
@@ -0,0 +1,17 @@
"--endian=little"
"--cpu=Cortex-M0"
"--fpu=None"
"-p"
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\CONFIG\debugger\Nuvoton\ionano100bn.ddf"
"--semihosting=none"
"--device=Nano100"
@@ -0,0 +1,13 @@
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armproc.dll"
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\..\..\..\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll"
"D:\0. Project_internal\2. Himpel\3. R_remocon\0. firmware\1. Nuvoton_R_remocon\1. V1_0\IAR\Release\Exe\LCD_Pixel_OnOff_Test.out"
--plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armbat.dll"
--flash_loader "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\config\flashloader\Nuvoton\Nano100_APROM.board"
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<crun>
<version>1</version>
<filter_entries>
<filter index="0" type="default">
<type>*</type>
<start_file>*</start_file>
<end_file>*</end_file>
<action_debugger>0</action_debugger>
<action_log>1</action_log>
</filter>
</filter_entries>
</crun>
@@ -0,0 +1,99 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Project>
<Desktop>
<Static>
<Debug-Log>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>1306</ColumnWidth1></Debug-Log>
<Build>
<ColumnWidth0>20</ColumnWidth0>
<ColumnWidth1>979</ColumnWidth1>
<ColumnWidth2>261</ColumnWidth2>
<ColumnWidth3>65</ColumnWidth3>
</Build>
<Workspace>
<ColumnWidths>
<Column0>124</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>
</Workspace>
<Disassembly>
<col-names>
<item>Disassembly</item><item>_I0</item></col-names>
<col-widths>
<item>500</item><item>20</item></col-widths>
<DisasmHistory/>
<PreferedWindows><Position>2</Position><ScreenPosX>0</ScreenPosX><ScreenPosY>0</ScreenPosY><Windows/></PreferedWindows><ShowCodeCoverage>1</ShowCodeCoverage><ShowInstrProfiling>1</ShowInstrProfiling></Disassembly>
<Find-in-Files>
<ColumnWidth0>404</ColumnWidth0><ColumnWidth1>67</ColumnWidth1><ColumnWidth2>606</ColumnWidth2><ColumnWidth3>269</ColumnWidth3></Find-in-Files>
<Register><RegFindHistory/></Register><StaticWatch><expressions><item>ADC3_Value</item><item>com</item><item>seg</item><item/></expressions><col-names><item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names><col-widths><item>100</item><item>150</item><item>100</item><item>100</item></col-widths></StaticWatch></Static>
<Windows>
<Wnd2>
<Tabs>
<Tab>
<Identity>TabID-2852-21951</Identity>
<TabName>Debug Log</TabName>
<Factory>Debug-Log</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-2329-21961</Identity>
<TabName>Build</TabName>
<Factory>Build</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-18160-24325</Identity>
<TabName>Find in Files</TabName>
<Factory>Find-in-Files</Factory>
<Session/>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd2><Wnd4>
<Tabs>
<Tab>
<Identity>TabID-13601-21954</Identity>
<TabName>Workspace</TabName>
<Factory>Workspace</Factory>
<Session>
<NodeDict><ExpandedNode>r_remocon</ExpandedNode><ExpandedNode>r_remocon/User</ExpandedNode></NodeDict></Session>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd4><Wnd5><Tabs><Tab><Identity>TabID-11458-436</Identity><TabName>Register</TabName><Factory>Register</Factory><Session><REG1>0</REG1><REG2>0</REG2><Group>12</Group><States>3</States><State0>CLK_PWRCTL</State0><State1>TMR0_TMR_CTL</State1><State2>TMR0_TMR_IER</State2></Session></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd5><Wnd7><Tabs><Tab><Identity>TabID-28239-27327</Identity><TabName>Live Watch</TabName><Factory>StaticWatch</Factory></Tab></Tabs><SelectedTab>0</SelectedTab></Wnd7></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>25</YPos2><SelStart2>742</SelStart2><SelEnd2>742</SelEnd2></Tab><ActiveTab>0</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\src\clk.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>547</YPos2><SelStart2>22330</SelStart2><SelEnd2>22330</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_system.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>81</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\Inc\timer.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>218</YPos2><SelStart2>7914</SelStart2><SelEnd2>7914</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\src\adc.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>162</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\Inc\lcd.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>32</YPos2><SelStart2>7671</SelStart2><SelEnd2>7671</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\Inc\sys.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>806</YPos2><SelStart2>61561</SelStart2><SelEnd2>61561</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-0276E628><key>iaridepm.enu1</key></Toolbar-0276E628></Sizes></Row0><Row1><Sizes><Toolbar-027BA538><key>debuggergui.enu1</key></Toolbar-027BA538></Sizes></Row1><Row2><Sizes/></Row2></Top><Left><Row0><Sizes><Wnd4><Rect><Top>-2</Top><Left>-2</Left><Bottom>689</Bottom><Right>198</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>104167</sizeHorzCX><sizeHorzCY>194553</sizeHorzCY><sizeVertCX>104167</sizeVertCX><sizeVertCY>672179</sizeVertCY></Rect></Wnd4></Sizes></Row0></Left><Right><Row0><Sizes><Wnd5><Rect><Top>-2</Top><Left>-2</Left><Bottom>689</Bottom><Right>356</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>104167</sizeHorzCX><sizeHorzCY>194553</sizeHorzCY><sizeVertCX>186458</sizeVertCX><sizeVertCY>672179</sizeVertCY></Rect></Wnd5></Sizes></Row0><Row1><Sizes><Wnd7><Rect><Top>-2</Top><Left>354</Left><Bottom>689</Bottom><Right>792</Right><x>354</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>104167</sizeHorzCX><sizeHorzCY>194553</sizeHorzCY><sizeVertCX>228125</sizeVertCX><sizeVertCY>672179</sizeVertCY></Rect></Wnd7></Sizes></Row1></Right><Bottom><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>267</Bottom><Right>1922</Right><x>-2</x><y>-2</y><xscreen>1924</xscreen><yscreen>269</yscreen><sizeHorzCX>1002083</sizeHorzCX><sizeHorzCY>261673</sizeHorzCY><sizeVertCX>104167</sizeVertCX><sizeVertCY>194553</sizeVertCY></Rect></Wnd2></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Project>
@@ -0,0 +1,70 @@
[Stack]
FillEnabled=0
OverflowWarningsEnabled=1
WarningThreshold=90
SpWarningsEnabled=1
WarnLogOnly=1
UseTrigger=1
TriggerName=main
LimitSize=0
ByteLimit=50
[InterruptLog]
LogEnabled=0
GraphEnabled=0
ShowTimeLog=1
SumEnabled=0
ShowTimeSum=1
SumSortOrder=0
[DataLog]
LogEnabled=0
GraphEnabled=0
ShowTimeLog=1
SumEnabled=0
ShowTimeSum=1
[Interrupts]
Enabled=1
[MemConfig]
Base=1
Manual=0
Ddf=1
TypeViol=0
Stop=1
[Trace1]
Enabled=0
ShowSource=1
[Simulator]
Freq=10000000
MultiCoreRunAll=1
[PlDriver]
MemConfigValue=C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\CONFIG\debugger\Nuvoton\ionano100bn.ddf
[Jet]
DisableInterrupts=0
LeaveRunning=0
MultiCoreRunAll=0
[ArmDriver]
EnableCache=1
[Breakpoints2]
Count=0
[DebugChecksum]
Checksum=-1743696445
[Exceptions]
StopOnUncaught=_ 0
StopOnThrow=_ 0
[CallStack]
ShowArgs=0
[Disassembly]
MixedMode=1
[Log file]
LoggingEnabled=_ 0
LogFile=_ ""
Category=_ 0
[TermIOLog]
LoggingEnabled=_ 0
LogFile=_ ""
[Disassemble mode]
mode=0
[Breakpoints]
Count=0
[Aliases]
Count=0
SuppressDialog=0
@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Workspace>
<ConfigDictionary>
<CurrentConfigs><Project>r_remocon/Release</Project></CurrentConfigs></ConfigDictionary>
<Desktop>
<Static>
<Debug-Log>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>1306</ColumnWidth1></Debug-Log>
<Workspace>
<ColumnWidths>
<Column0>204</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>
</Workspace>
<Build>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>979</ColumnWidth1><ColumnWidth2>261</ColumnWidth2><ColumnWidth3>65</ColumnWidth3></Build>
<TerminalIO/>
<Find-in-Files>
<ColumnWidth0>569</ColumnWidth0>
<ColumnWidth1>94</ColumnWidth1>
<ColumnWidth2>854</ColumnWidth2>
<ColumnWidth3>379</ColumnWidth3>
</Find-in-Files>
</Static>
<Windows>
<Wnd0>
<Tabs>
<Tab>
<Identity>TabID-12019-6175</Identity>
<TabName>Workspace</TabName>
<Factory>Workspace</Factory>
<Session>
<NodeDict><ExpandedNode>r_remocon</ExpandedNode><ExpandedNode>r_remocon/Libraries</ExpandedNode><ExpandedNode>r_remocon/User</ExpandedNode></NodeDict></Session>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd0><Wnd1>
<Tabs>
<Tab>
<Identity>TabID-22767-6178</Identity>
<TabName>Debug Log</TabName>
<Factory>Debug-Log</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-225-6191</Identity>
<TabName>Build</TabName>
<Factory>Build</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-5649-25722</Identity>
<TabName>Find in Files</TabName>
<Factory>Find-in-Files</Factory>
<Session/>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd1></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>37</YPos2><SelStart2>760</SelStart2><SelEnd2>760</SelEnd2></Tab><ActiveTab>0</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\src\clk.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>547</YPos2><SelStart2>22330</SelStart2><SelEnd2>22330</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_system.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>81</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\Inc\timer.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>218</YPos2><SelStart2>7914</SelStart2><SelEnd2>7914</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\src\adc.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>162</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\Inc\lcd.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>32</YPos2><SelStart2>7671</SelStart2><SelEnd2>7671</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\Library\StdDriver\Inc\sys.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>806</YPos2><SelStart2>61561</SelStart2><SelEnd2>61561</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-00F0D790><key>iaridepm.enu1</key></Toolbar-00F0D790></Sizes></Row0></Top><Left><Row0><Sizes><Wnd0><Rect><Top>-2</Top><Left>-2</Left><Bottom>720</Bottom><Right>278</Right><x>-2</x><y>-2</y><xscreen>280</xscreen><yscreen>262</yscreen><sizeHorzCX>145833</sizeHorzCX><sizeHorzCY>254864</sizeHorzCY><sizeVertCX>145833</sizeVertCX><sizeVertCY>702335</sizeVertCY></Rect></Wnd0></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd1><Rect><Top>-2</Top><Left>-2</Left><Bottom>260</Bottom><Right>1922</Right><x>-2</x><y>-2</y><xscreen>1924</xscreen><yscreen>262</yscreen><sizeHorzCX>1002083</sizeHorzCX><sizeHorzCY>254864</sizeHorzCY><sizeVertCX>145833</sizeVertCX><sizeVertCY>254864</sizeVertCY></Rect></Wnd1></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Workspace>
@@ -0,0 +1,2 @@
[MainWindow]
WindowPlacement=_ 2049 169 3436 1024 3
@@ -0,0 +1,40 @@
@REM This batch file has been generated by the IAR Embedded Workbench
@REM C-SPY Debugger, as an aid to preparing a command line for running
@REM the cspybat command line utility using the appropriate settings.
@REM
@REM Note that this file is generated every time a new debug session
@REM is initialized, so you may want to move or rename the file before
@REM making changes.
@REM
@REM You can launch cspybat by typing the name of this batch file followed
@REM by the name of the debug file (usually an ELF/DWARF or UBROF file).
@REM
@REM Read about available command line parameters in the C-SPY Debugging
@REM Guide. Hints about additional command line parameters that may be
@REM useful in specific cases:
@REM --download_only Downloads a code image without starting a debug
@REM session afterwards.
@REM --silent Omits the sign-on message.
@REM --timeout Limits the maximum allowed execution time.
@REM
@echo off
if not "%~1" == "" goto debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\2. Himpel\4. RH_roomcon\0. firmware\1. Nuvoton_RH_roomcon_V1.0\IAR\settings\rh_roomcon.Release.general.xcl" --backend -f "D:\0. Project_internal\2. Himpel\4. RH_roomcon\0. firmware\1. Nuvoton_RH_roomcon_V1.0\IAR\settings\rh_roomcon.Release.driver.xcl"
@echo off
goto end
:debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\2. Himpel\4. RH_roomcon\0. firmware\1. Nuvoton_RH_roomcon_V1.0\IAR\settings\rh_roomcon.Release.general.xcl" "--debug_file=%~1" --backend -f "D:\0. Project_internal\2. Himpel\4. RH_roomcon\0. firmware\1. Nuvoton_RH_roomcon_V1.0\IAR\settings\rh_roomcon.Release.driver.xcl"
@echo off
:end
@@ -0,0 +1,17 @@
"--endian=little"
"--cpu=Cortex-M0"
"--fpu=None"
"-p"
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\CONFIG\debugger\Nuvoton\ionano100bn.ddf"
"--semihosting=none"
"--device=Nano100"
@@ -0,0 +1,13 @@
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armproc.dll"
"C:\Program Files (x86)\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll"
"D:\0. Project_internal\2. Himpel\4. RH_roomcon\0. firmware\1. Nuvoton_RH_roomcon_V1.0\IAR\Release\Exe\LCD_Pixel_OnOff_Test.out"
--plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armbat.dll"
--flash_loader "D:\0. Project_internal\2. Himpel\4. RH_roomcon\0. firmware\1. Nuvoton_RH_roomcon_V1.0\IAR\rh_roomcon.board"
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<crun>
<version>1</version>
<filter_entries>
<filter index="0" type="default">
<type>*</type>
<start_file>*</start_file>
<end_file>*</end_file>
<action_debugger>0</action_debugger>
<action_log>1</action_log>
</filter>
</filter_entries>
</crun>
File diff suppressed because one or more lines are too long
@@ -0,0 +1,92 @@
[Stack]
FillEnabled=0
OverflowWarningsEnabled=1
WarningThreshold=90
SpWarningsEnabled=1
WarnLogOnly=1
UseTrigger=1
TriggerName=main
LimitSize=0
ByteLimit=50
[DebugChecksum]
Checksum=1496114437
[CodeCoverage]
Enabled=_ 0
[Exceptions]
StopOnUncaught=_ 0
StopOnThrow=_ 0
[CallStack]
ShowArgs=0
[Disassembly]
MixedMode=1
[DriverProfiling]
Enabled=0
Mode=1
Graph=0
Symbiont=0
Exclusions=
[CallStackLog]
Enabled=0
[CallStackStripe]
ShowTiming=1
[InterruptLog]
LogEnabled=0
GraphEnabled=0
ShowTimeLog=1
SumEnabled=0
ShowTimeSum=1
SumSortOrder=0
[DataLog]
LogEnabled=0
GraphEnabled=0
ShowTimeLog=1
SumEnabled=0
ShowTimeSum=1
[Breakpoints2]
Bp0=_ 1 "STD_CODE2" "{$PROJ_DIR$\..\main.c}.52.5" 0 0 1 "" 0 ""
Bp1=_ 1 "STD_CODE2" "{$PROJ_DIR$\..\main.c}.47.2" 0 0 1 "" 0 ""
Bp2=_ 1 "STD_CODE2" "{$PROJ_DIR$\..\My_system.c}.233.5" 0 0 1 "" 0 ""
Bp3=_ 1 "STD_CODE2" "{$PROJ_DIR$\..\My_system.c}.221.5" 0 0 1 "" 0 ""
Bp4=_ 1 "STD_CODE2" "{$PROJ_DIR$\..\My_system.c}.224.5" 0 0 1 "" 0 ""
Bp5=_ 1 "STD_CODE2" "{$PROJ_DIR$\..\My_system.c}.230.5" 0 0 1 "" 0 ""
Bp6=_ 1 "STD_CODE2" "{$PROJ_DIR$\..\My_system.c}.218.5" 0 0 1 "" 0 ""
Count=7
[Interrupts]
Enabled=1
[MemConfig]
Base=1
Manual=0
Ddf=1
TypeViol=0
Stop=1
[Trace1]
Enabled=0
ShowSource=1
[Simulator]
Freq=10000000
MultiCoreRunAll=1
[array_types]
Fmt0=uint8_t[20] 4 0
Fmt1=uint8_t[2] 4 0
Fmt2=uint8_t[30] 4 0
Fmt3=uint8_t[3] 3 0
[watch_formats]
Fmt0={W}1:Written_Data[1] 4 0
Fmt1={W}1:Written_Data[2] 4 0
Fmt2={W}42:Pre_Touch_data 4 0
Fmt3={W}42:Touch_data 4 0
Fmt4={W}42:g_u8DeviceAddr 4 0
[Log file]
LoggingEnabled=_ 0
LogFile=_ ""
Category=_ 0
[TermIOLog]
LoggingEnabled=_ 0
LogFile=_ ""
[Disassemble mode]
mode=0
[Breakpoints]
Count=0
[Aliases]
Count=0
SuppressDialog=0
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
[MainWindow]
WindowPlacement=_ 2166 172 3553 923 1
@@ -0,0 +1,40 @@
@REM This batch file has been generated by the IAR Embedded Workbench
@REM C-SPY Debugger, as an aid to preparing a command line for running
@REM the cspybat command line utility using the appropriate settings.
@REM
@REM Note that this file is generated every time a new debug session
@REM is initialized, so you may want to move or rename the file before
@REM making changes.
@REM
@REM You can launch cspybat by typing the name of this batch file followed
@REM by the name of the debug file (usually an ELF/DWARF or UBROF file).
@REM
@REM Read about available command line parameters in the C-SPY Debugging
@REM Guide. Hints about additional command line parameters that may be
@REM useful in specific cases:
@REM --download_only Downloads a code image without starting a debug
@REM session afterwards.
@REM --silent Omits the sign-on message.
@REM --timeout Limits the maximum allowed execution time.
@REM
@echo off
if not "%~1" == "" goto debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\2. Himpel\1.1 Heuven_s2\0. firmware\1. Nuvoton_S2_roomcon_V1.0_S400\IAR\settings\s2_roomcon.Release.general.xcl" --backend -f "D:\0. Project_internal\2. Himpel\1.1 Heuven_s2\0. firmware\1. Nuvoton_S2_roomcon_V1.0_S400\IAR\settings\s2_roomcon.Release.driver.xcl"
@echo off
goto end
:debugFile
@echo on
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\common\bin\cspybat" -f "D:\0. Project_internal\2. Himpel\1.1 Heuven_s2\0. firmware\1. Nuvoton_S2_roomcon_V1.0_S400\IAR\settings\s2_roomcon.Release.general.xcl" "--debug_file=%~1" --backend -f "D:\0. Project_internal\2. Himpel\1.1 Heuven_s2\0. firmware\1. Nuvoton_S2_roomcon_V1.0_S400\IAR\settings\s2_roomcon.Release.driver.xcl"
@echo off
:end
@@ -0,0 +1,17 @@
"--endian=little"
"--cpu=Cortex-M0"
"--fpu=None"
"-p"
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\CONFIG\debugger\Nuvoton\ionano100bn.ddf"
"--semihosting=none"
"--device=Nano100"
@@ -0,0 +1,13 @@
"C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armproc.dll"
"C:\Program Files (x86)\Nuvoton Tools\Nu-Link_IAR\Nu-Link_IAR.dll"
"D:\0. Project_internal\2. Himpel\1.1 Heuven_s2\0. firmware\1. Nuvoton_S2_roomcon_V1.0_S400\IAR\Release\Exe\LCD_Pixel_OnOff_Test.out"
--plugin "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\bin\armbat.dll"
--flash_loader "C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\config\flashloader\Nuvoton\Nano100_APROM.board"
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<crun>
<version>1</version>
<filter_entries>
<filter index="0" type="default">
<type>*</type>
<start_file>*</start_file>
<end_file>*</end_file>
<action_debugger>0</action_debugger>
<action_log>1</action_log>
</filter>
</filter_entries>
</crun>
@@ -0,0 +1,179 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Project>
<Desktop>
<Static>
<Debug-Log>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>1857</ColumnWidth1></Debug-Log>
<Build>
<ColumnWidth0>20</ColumnWidth0>
<ColumnWidth1>1392</ColumnWidth1>
<ColumnWidth2>371</ColumnWidth2>
<ColumnWidth3>92</ColumnWidth3>
</Build>
<Workspace>
<ColumnWidths>
<Column0>257</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>
</Workspace>
<Disassembly>
<PreferedWindows>
<Position>2</Position>
<ScreenPosX>0</ScreenPosX>
<ScreenPosY>0</ScreenPosY>
<Windows/>
</PreferedWindows>
<col-names>
<item>Disassembly</item><item>_I0</item></col-names>
<col-widths>
<item>500</item><item>20</item></col-widths>
<DisasmHistory/>
<ShowCodeCoverage>1</ShowCodeCoverage><ShowInstrProfiling>1</ShowInstrProfiling></Disassembly>
<StaticWatch>
<expressions>
<item>Touch_Event</item><item>Touch_data</item><item>CO2_Value</item><item>Pm_1_0_value</item><item>Pm_2_5_value</item><item>Pm_10_value</item><item>Rx_CO2_Buff</item><item>Tx_CO2_Buff</item><item>temperature_val</item><item>humidity_val</item><item>rawValueTemp</item><item>rawValueHumi</item><item>ht_read_data</item><item>rLcd.Icon.Number_Hour</item><item>rLcd.Icon.hour</item><item>Test_Mode_Step</item><item>Reservation_Blink_Count</item><item>Tx_Main_buffer</item><item>VSP_Mode_Event</item><item/></expressions>
<col-names>
<item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names>
<col-widths>
<item>151</item><item>150</item><item>100</item><item>178</item></col-widths>
</StaticWatch>
<Find-All-Declarations>
<ColumnWidth0>664</ColumnWidth0>
<ColumnWidth1>94</ColumnWidth1>
<ColumnWidth2>1138</ColumnWidth2>
</Find-All-Declarations>
<WATCH_1>
<expressions>
<item>result</item><item/></expressions>
<col-names>
<item>Expression</item><item>Location</item><item>Type</item><item>Value</item></col-names>
<col-widths>
<item>100</item><item>150</item><item>100</item><item>100</item></col-widths>
</WATCH_1>
<Find-in-Files><ColumnWidth0>569</ColumnWidth0><ColumnWidth1>94</ColumnWidth1><ColumnWidth2>854</ColumnWidth2><ColumnWidth3>379</ColumnWidth3></Find-in-Files></Static>
<Windows>
<Wnd0>
<Tabs>
<Tab>
<Identity>TabID-27113-10701</Identity>
<TabName>Debug Log</TabName>
<Factory>Debug-Log</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-26591-10711</Identity>
<TabName>Build</TabName>
<Factory>Build</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-2773-10953</Identity>
<TabName>Declarations</TabName>
<Factory>Find-All-Declarations</Factory>
<Session/>
</Tab>
<Tab><Identity>TabID-17511-22350</Identity><TabName>Find in Files</TabName><Factory>Find-in-Files</Factory><Session/></Tab></Tabs>
<SelectedTab>0</SelectedTab></Wnd0><Wnd1>
<Tabs>
<Tab>
<Identity>TabID-5094-10705</Identity>
<TabName>Workspace</TabName>
<Factory>Workspace</Factory>
<Session>
<NodeDict><ExpandedNode>s2_roomcon</ExpandedNode><ExpandedNode>s2_roomcon/User</ExpandedNode></NodeDict></Session>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd1><Wnd2>
<Tabs>
<Tab>
<Identity>TabID-26883-10910</Identity>
<TabName>Live Watch</TabName>
<Factory>StaticWatch</Factory>
</Tab>
<Tab>
<Identity>TabID-1610-28560</Identity>
<TabName>Watch 1</TabName>
<Factory>WATCH_1</Factory>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd2><Wnd3>
<Tabs>
<Tab>
<Identity>TabID-20255-15538</Identity>
<TabName>Disassembly</TabName>
<Factory>Disassembly</Factory>
<Session/>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd3></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\doc\infocenter\index.ENU.html</Filename></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_HTsensor.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>258</YPos2><SelStart2>5102</SelStart2><SelEnd2>5102</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_Uart.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>245</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_system.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>422</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\..\1. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\Library\StdDriver\inc\i2c.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>44</YPos2><SelStart2>1692</SelStart2><SelEnd2>1692</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\typedefs.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>36</YPos2><SelStart2>3099</SelStart2><SelEnd2>3099</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_define.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>256</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\sht3x.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>102</YPos2><SelStart2>5394</SelStart2><SelEnd2>5394</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_Melody.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>0</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_LCM.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>385</YPos2><SelStart2>8765</SelStart2><SelEnd2>8765</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>35</YPos2><SelStart2>1472</SelStart2><SelEnd2>1472</SelEnd2></Tab><ActiveTab>10</ActiveTab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\..\1. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\Library\StdDriver\src\clk.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>544</YPos2><SelStart2>22516</SelStart2><SelEnd2>22516</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\MyTouch.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>597</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-001AD9B0><key>iaridepm.enu1</key></Toolbar-001AD9B0></Sizes></Row0><Row1><Sizes><Toolbar-00225298><key>debuggergui.enu1</key></Toolbar-00225298></Sizes></Row1><Row2><Sizes/></Row2></Top><Left><Row0><Sizes><Wnd1><Rect><Top>-2</Top><Left>-2</Left><Bottom>752</Bottom><Right>331</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>104167</sizeHorzCX><sizeHorzCY>195695</sizeHorzCY><sizeVertCX>173438</sizeVertCX><sizeVertCY>737769</sizeVertCY></Rect></Wnd1></Sizes></Row0></Left><Right><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>752</Bottom><Right>570</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>104167</sizeHorzCX><sizeHorzCY>195695</sizeHorzCY><sizeVertCX>297917</sizeVertCX><sizeVertCY>737769</sizeVertCY></Rect></Wnd2></Sizes></Row0><Row1><Sizes><Wnd3><Rect><Top>-2</Top><Left>568</Left><Bottom>752</Bottom><Right>768</Right><x>568</x><y>-2</y><xscreen>200</xscreen><yscreen>200</yscreen><sizeHorzCX>104167</sizeHorzCX><sizeHorzCY>195695</sizeHorzCY><sizeVertCX>104167</sizeVertCX><sizeVertCY>737769</sizeVertCY></Rect></Wnd3></Sizes></Row1></Right><Bottom><Row0><Sizes><Wnd0><Rect><Top>-2</Top><Left>-2</Left><Bottom>198</Bottom><Right>1922</Right><x>-2</x><y>-2</y><xscreen>1924</xscreen><yscreen>200</yscreen><sizeHorzCX>1002083</sizeHorzCX><sizeHorzCY>195695</sizeHorzCY><sizeVertCX>104167</sizeVertCX><sizeVertCY>195695</sizeVertCY></Rect></Wnd0></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Project>
@@ -0,0 +1,45 @@
[Stack]
FillEnabled=0
OverflowWarningsEnabled=1
WarningThreshold=90
SpWarningsEnabled=1
WarnLogOnly=1
UseTrigger=1
TriggerName=main
LimitSize=0
ByteLimit=50
[DebugChecksum]
Checksum=-784627229
[Exceptions]
StopOnUncaught=_ 0
StopOnThrow=_ 0
[CallStack]
ShowArgs=0
[Disassembly]
MixedMode=1
[array_types]
Fmt0=uint8_t[10] 4 0
Fmt1=uint8_t[15] 4 0
Fmt2=uint8_t[6] 4 0
[watch_formats]
Fmt0={W}1:cksum_hi 4 0
Fmt1={W}1:cksum_low 4 0
Fmt2={W}1:result 4 0
Fmt3={W}42:Touch_Event 3 0
Fmt4={W}42:Touch_data 4 0
Fmt5={W}42:rLcd.Number_Hour 3 0
Fmt6={W}42:serialNumber 4 0
[Log file]
LoggingEnabled=_ 0
LogFile=_ ""
Category=_ 0
[TermIOLog]
LoggingEnabled=_ 0
LogFile=_ ""
[Disassemble mode]
mode=0
[Breakpoints]
Count=0
[Aliases]
Count=0
SuppressDialog=0
@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<Workspace>
<ConfigDictionary>
<CurrentConfigs/></ConfigDictionary>
<Desktop>
<Static>
<Workspace>
<ColumnWidths>
<Column0>389</Column0><Column1>27</Column1><Column2>27</Column2><Column3>27</Column3></ColumnWidths>
</Workspace>
<Debug-Log>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>1306</ColumnWidth1></Debug-Log>
<Build>
<ColumnWidth0>20</ColumnWidth0><ColumnWidth1>979</ColumnWidth1><ColumnWidth2>261</ColumnWidth2><ColumnWidth3>65</ColumnWidth3></Build>
<Find-in-Files>
<ColumnWidth0>569</ColumnWidth0><ColumnWidth1>94</ColumnWidth1><ColumnWidth2>854</ColumnWidth2><ColumnWidth3>379</ColumnWidth3></Find-in-Files>
<TerminalIO/></Static>
<Windows>
<Wnd2>
<Tabs>
<Tab>
<Identity>TabID-26817-17684</Identity>
<TabName>Workspace</TabName>
<Factory>Workspace</Factory>
<Session>
<NodeDict/></Session>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd2><Wnd3>
<Tabs>
<Tab>
<Identity>TabID-2016-18354</Identity>
<TabName>Build</TabName>
<Factory>Build</Factory>
<Session/>
</Tab>
<Tab>
<Identity>TabID-22237-18589</Identity>
<TabName>Find in Files</TabName>
<Factory>Find-in-Files</Factory>
<Session/>
</Tab>
</Tabs>
<SelectedTab>0</SelectedTab></Wnd3></Windows>
<Editor>
<Pane><Tab><Factory>TextEditor</Factory><Filename>C:\Program Files (x86)\IAR Systems\Embedded Workbench 7.5\arm\doc\infocenter\index.ENU.html</Filename></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_Uart.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>245</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_system.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>346</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\..\1. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\Library\StdDriver\inc\i2c.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>44</YPos2><SelStart2>1692</SelStart2><SelEnd2>1692</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\typedefs.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>36</YPos2><SelStart2>3099</SelStart2><SelEnd2>3099</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\My_define.h</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>161</YPos2><SelStart2>0</SelStart2><SelEnd2>0</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\main.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>118</YPos2><SelStart2>1447</SelStart2><SelEnd2>1447</SelEnd2></Tab><Tab><Factory>TextEditor</Factory><Filename>$WS_DIR$\..\..\..\..\..\1. Nuvoton\Nano100B_Series_BSP_CMSIS_v3.03.000\Library\StdDriver\src\clk.c</Filename><XPos>0</XPos><YPos>0</YPos><SelStart>0</SelStart><SelEnd>0</SelEnd><XPos2>0</XPos2><YPos2>544</YPos2><SelStart2>22516</SelStart2><SelEnd2>22516</SelEnd2></Tab><ActiveTab>7</ActiveTab></Pane><ActivePane>0</ActivePane><Sizes><Pane><X>1000000</X><Y>1000000</Y></Pane></Sizes><SplitMode>1</SplitMode></Editor>
<Positions>
<Top><Row0><Sizes><Toolbar-00E7A718><key>iaridepm.enu1</key></Toolbar-00E7A718></Sizes></Row0></Top><Left><Row0><Sizes><Wnd2><Rect><Top>-2</Top><Left>-2</Left><Bottom>408</Bottom><Right>463</Right><x>-2</x><y>-2</y><xscreen>200</xscreen><yscreen>191</yscreen><sizeHorzCX>146092</sizeHorzCX><sizeHorzCY>247730</sizeHorzCY><sizeVertCX>339664</sizeVertCX><sizeVertCY>531777</sizeVertCY></Rect></Wnd2></Sizes></Row0></Left><Right><Row0><Sizes/></Row0></Right><Bottom><Row0><Sizes><Wnd3><Rect><Top>-2</Top><Left>-2</Left><Bottom>315</Bottom><Right>1371</Right><x>-2</x><y>-2</y><xscreen>1373</xscreen><yscreen>317</yscreen><sizeHorzCX>1002922</sizeHorzCX><sizeHorzCY>411154</sizeHorzCY><sizeVertCX>146092</sizeVertCX><sizeVertCY>247730</sizeVertCY></Rect></Wnd3></Sizes></Row0></Bottom><Float><Sizes/></Float></Positions>
</Desktop>
</Workspace>
@@ -0,0 +1,2 @@
[MainWindow]
WindowPlacement=_ 503 124 1890 971 1
+4
View File
@@ -0,0 +1,4 @@
+354
View File
@@ -0,0 +1,354 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "Nano100Series.h"
#include "adc.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "uart.h"
#include "sys.h"
#include "clk.h"
#include "My_define.h"
const unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
// Table of CRC values for low-order byte
const unsigned char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
uint16_t CRC16(uint8_t *puchMsg, uint16_t usDataLen)
{
uint8_t uchCRCHi = 0xFF ; // high CRC byte initialized
uint8_t uchCRCLo = 0xFF ; // low CRC byte initialized
uint8_t uIndex ; // will index into CRC lookup table
while (usDataLen--) // pass through message buffer
{
uIndex = uchCRCHi ^ *puchMsg++ ; // calculate the CRC
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return ((uint16_t)uchCRCHi << 8 | (uint16_t)uchCRCLo) ;
}
uint16_t Aeverage_calculator(uint16_t val, uint16_t * array_val)
{
uint8_t i;
uint16_t max = 0;
uint16_t min = 10000;
uint32_t sum = 0;
uint16_t Rval = 0;
for(i=9; i>0; i--)
{
*(array_val+i) = *(array_val+i-1);
}
*array_val = val;
for(i=0; i<10; i++)
{
if(array_val[i] >= max)
{
max = array_val[i];
}
if(array_val[i] <= min)
{
min = array_val[i];
}
sum += array_val[i];
}
Rval = (uint16_t)((sum - max - min)/8);
return(Rval);
}
///////////////////////////////////////////////////////////////////////////////
uint8_t Rx_FND_buff[50] ={0,};
uint8_t Tx_FND_buff[50] ={0,};
uint8_t FND_Packet_Type = 0;
uint8_t FND_Packet_Length = 0;
uint8_t Rx_FND_Pos = 0;
volatile uint8_t Rx_FND_complete = 0;
void Rx_FND_Check(uint8_t data)
{
uint16_t iTmp = 0, icrc = 0;
if(Rx_FND_TimeOut == 0)Rx_FND_Pos = 0;
switch(Rx_FND_Pos)
{
case 0:
if(data != 0xAA)break;
Rx_FND_buff[Rx_FND_Pos++] = data;
break;
case 1:
if(data != 0x01){Rx_FND_Pos = 0; break;}
Rx_FND_buff[Rx_FND_Pos++] = data;
break;
case 2:
Rx_FND_buff[Rx_FND_Pos++] = data;
if(data == 0x03){FND_Packet_Type = 0x02;Rx_FND_Pos = 0;} //RoomCon
else{FND_Packet_Type = 0x01;} //Diffuser
break;
case 3:
Rx_FND_buff[Rx_FND_Pos++] = data;
FND_Packet_Length = 39;
break;
case 4:
Rx_FND_buff[Rx_FND_Pos++] = data;
if(FND_Packet_Type == 0x02)
{
if((data == 0x01)||(data == 0x02)||(data == 0x03)) //29byte
{
FND_Packet_Length = 39;
}
} //RoomCon
break;
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
Rx_FND_buff[Rx_FND_Pos++] = data;
break;
case 28:
Rx_FND_buff[Rx_FND_Pos++] = data;
if(FND_Packet_Length == 29)
{
iTmp = (uint16_t)Rx_FND_buff[27]<<8;
icrc = iTmp + (uint16_t)Rx_FND_buff[28] ;
if(icrc == CRC16(Rx_FND_buff, 27))
{
Rx_FND_complete = 1;
}
Rx_FND_Pos = 0;
}
break;
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
Rx_FND_buff[Rx_FND_Pos++] = data;
break;
case 38:
Rx_FND_buff[Rx_FND_Pos++] = data;
if(FND_Packet_Length == 39)
{
iTmp = (uint16_t)Rx_FND_buff[37]<<8;
icrc = iTmp + (uint16_t)Rx_FND_buff[38] ;
if(icrc == CRC16(Rx_FND_buff, 37))
{
Rx_FND_complete = 1;
}
Rx_FND_Pos = 0;
}
break;
default:
Rx_FND_Pos = 0;
break;
}
}
void com_FND_process(void)
{
if(Rx_FND_complete == 1)
{
Rx_FND_complete = 0;
Rx_Sensor_Parsing();
}
}
uint8_t CheckSum_Creator(uint8_t *buf, uint8_t len)
{
uint8_t i, rt;
rt = 0;
for(i=0; i<len; i++)
{
rt ^= buf[i];
}
return(rt);
}
void UART1_HANDLE() // modbus
{
uint8_t u8InChar=0xFF;
uint32_t u32IntSts= UART1->ISR;
if(u32IntSts & UART_ISR_RDA_IS_Msk)
{
u8InChar = UART_READ(UART1); /* Rx trigger level is 1 byte*/
Rx_FND_Check(u8InChar);
Rx_FND_TimeOut = 5;
}
if(u32IntSts & UART_ISR_THRE_IS_Msk)
{
;
}
}
void UART1_IRQHandler(void) // modbus
{
UART1_HANDLE();
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////
uint16_t SEN66_pm10p0 = 0;
uint16_t SEN66_pm4p0 = 0;
uint16_t SEN66_pm2p5 = 0;
uint16_t SEN66_pm1p0 = 0;
uint16_t SEN66_humidity_value = 0;
uint16_t SEN66_temperature_value = 0;
uint16_t SEN66_VOC_value = 0;
uint16_t SEN66_NOx_value = 0;
uint16_t SEN66_CO2_value = 0;
extern uint8_t Power_On;
void Rx_Sensor_Parsing(void)
{
if(Rx_FND_buff[2] != 0x02)return;
Power_On = Rx_FND_buff[5]&0x01;
SEN66_pm10p0 = ((uint16_t)Rx_FND_buff[12]<<8 | (uint16_t)Rx_FND_buff[13]);
SEN66_pm4p0 = ((uint16_t)Rx_FND_buff[14]<<8 | (uint16_t)Rx_FND_buff[15]);
SEN66_pm2p5 = ((uint16_t)Rx_FND_buff[16]<<8 | (uint16_t)Rx_FND_buff[17]);
SEN66_pm1p0 = ((uint16_t)Rx_FND_buff[18]<<8 | (uint16_t)Rx_FND_buff[19]);
SEN66_humidity_value = ((uint16_t)Rx_FND_buff[20]<<8 | (uint16_t)Rx_FND_buff[21]);
SEN66_temperature_value = ((uint16_t)Rx_FND_buff[22]<<8 | (uint16_t)Rx_FND_buff[23]);
SEN66_VOC_value = ((uint16_t)Rx_FND_buff[24]<<8 | (uint16_t)Rx_FND_buff[25]);
SEN66_NOx_value = ((uint16_t)Rx_FND_buff[26]<<8 | (uint16_t)Rx_FND_buff[27]);
SEN66_CO2_value = ((uint16_t)Rx_FND_buff[28]<<8 | (uint16_t)Rx_FND_buff[29]);
}
void UART0_HANDLE() // co2
{
uint8_t u8InChar=0xFF;
uint32_t u32IntSts= UART0->ISR;
if(u32IntSts & UART_ISR_RDA_IS_Msk)
{
u8InChar = UART_READ(UART0); /* Rx trigger level is 1 byte*/
}
if(u32IntSts & UART_ISR_THRE_IS_Msk)
{
;
}
}
void UART0_IRQHandler(void) // co2
{
UART0_HANDLE();
}
+57
View File
@@ -0,0 +1,57 @@
void Display_update(void);
void Display_process(void);
void Initial_Signal();
void Disp_Segdata(uint8_t Sel, uint8_t digit4,uint8_t digit3, uint8_t digit2, uint8_t digit1);
void Led_OnOff(uint8_t kind, uint8_t onoff);
void delay_ms(uint32_t ms);
void delay_us(uint32_t us);
void PowerDownFunction(void);
void GPIO_Init(void);
void PWM_Init(void);
void Timer0_Init(void);
void Timer1_Init(void);
void Timer2_Init(void);
void SYS_Init(void);
void UART0_Init(void);
void UART1_Init(void);
void SC0_Init();
void SC1_Init();
void ADC_Init(void);
void Processor_Init(void);
void Rx_Sensor_Parsing(void);
void com_FND_process(void);
#define ST_LED PA11
#define IN485_DIR PB6
#define FND_POWER PA1
#define FND_VERSION 1
#define EEP_ADDR_START 0x05
extern uint16_t SEN66_pm10p0;
extern uint16_t SEN66_pm4p0;
extern uint16_t SEN66_pm2p5;
extern uint16_t SEN66_pm1p0;
extern uint16_t SEN66_humidity_value;
extern uint16_t SEN66_temperature_value;
extern uint16_t SEN66_VOC_value;
extern uint16_t SEN66_NOx_value;
extern uint16_t SEN66_CO2_value;
extern volatile uint8_t Run_Timer;
extern volatile uint16_t mSec_Timer;
extern volatile uint16_t Blink_Timer;
extern volatile uint8_t Rx_FND_TimeOut;
extern volatile uint16_t FastBlink_Timer;
+478
View File
@@ -0,0 +1,478 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "Nano100Series.h"
#include "adc.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "uart.h"
#include "sys.h"
#include "clk.h"
#include "EEPROM_Emulate.h"
#include "My_define.h"
void delay_us(uint32_t us)
{
CLK_SysTickDelay(us);
}
void delay_ms(uint32_t ms)
{
while(ms--)
{
delay_us(1000);
}
}
void UART0_Init()//co2
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
SYS_ResetModule(UART0_RST);
UART_Open(UART0, 115200);
UART_EnableInt(UART0, UART_IER_RDA_IE_Msk);
NVIC_EnableIRQ(UART0_IRQn);
}
void UART1_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
SYS_ResetModule(UART1_RST);
UART_Open(UART1, 115200);
UART_EnableInt(UART1, UART_IER_RDA_IE_Msk);
NVIC_EnableIRQ(UART1_IRQn);
}
void SC0_Init() // to main
{
SCUART_Open(SC0, 1200);
// Enable smartcard receive interrupt
SCUART_ENABLE_INT(SC0, SC_IER_RDA_IE_Msk);
NVIC_EnableIRQ(SC0_IRQn);
}
void SC1_Init() // to dust
{
SCUART_Open(SC1, 9600);
// Enable smartcard receive interrupt
SCUART_ENABLE_INT(SC1, SC_IER_RDA_IE_Msk);
NVIC_EnableIRQ(SC1_IRQn);
}
void PowerDownFunction(void)
{
;
}
#define IR_EVENT_POWER 0x01
#define IR_EVENT_MODE 0x02
#define IR_EVENT_WIND_UP 0x04
#define IR_EVENT_WIND_DN 0x05
#define IR_EVENT_TIME_1 0x06
#define IR_EVENT_TIME_2 0x07
#define IR_EVENT_TIME_3 0x08
#define IR_EVENT_FILTER_RESET 0x09
#define IR_START 13500
#define IR_HIGH 2260
#define IR_LOW 1180
#define IR_STOP 600
#define IR_REPEAT 11200
uint16_t long_timer1 = 0;
uint16_t remocon_buff[4];
uint8_t remocon_pos = 0;
uint8_t remocon_bit_count = 0;
uint8_t IR_Event_Code = 0;
volatile uint8_t IR_Event_Flag = 0;
void IR_Receive(void)
{
uint16_t tmp = 0;
long_timer1 = TIMER2->DR/12;
TIMER2->CTL |= TIMER_CTL_SW_RST_Msk;
TIMER_Start(TIMER2);
if((long_timer1 > IR_START-300)&&(long_timer1 < IR_START+300))
{
remocon_buff[0] = 0;
remocon_buff[1] = 0;
remocon_bit_count = 0;
remocon_pos = 0;
}
else if((long_timer1 > IR_REPEAT-300)&&(long_timer1 < IR_REPEAT+300))
{
remocon_buff[0] = 0;
remocon_buff[1] = 0;
remocon_bit_count = 0;
remocon_pos = 0;
}
else if((long_timer1 > IR_HIGH-200)&&(long_timer1 < IR_HIGH+200))
{
remocon_buff[remocon_pos] |= 0x8000;
if(remocon_bit_count++ >= 15){remocon_bit_count = 0;remocon_pos=1;}
else {remocon_buff[remocon_pos] >>= 1;}
}
else if((long_timer1 > IR_LOW-200)&&(long_timer1 < IR_LOW+200))
{
remocon_buff[remocon_pos] &= ~0x8000;
if(remocon_bit_count++ >= 15){remocon_bit_count = 0;remocon_pos=1;}
else {remocon_buff[remocon_pos] >>= 1;}
}
if((remocon_pos == 1)&&(remocon_bit_count == 15))
{
if(remocon_buff[0] == 0xA55A)
{
tmp = remocon_buff[1];
/* switch(tmp)
{
case 0x6E11: // Power
IR_Event_Code = IR_EVENT_POWER;
break;
case 0x6D12: // mode
IR_Event_Code = IR_EVENT_MODE;
break;
case 0x6C13: // up
IR_Event_Code = IR_EVENT_WIND_UP;
break;
case 0x6817: // dn
IR_Event_Code = IR_EVENT_WIND_DN;
break;
case 0x6718: // 1hour
IR_Event_Code = IR_EVENT_TIME_1 ;
break;
case 0x6619: // 2hour
IR_Event_Code = IR_EVENT_TIME_2 ;
break;
case 0x215E: // 3hour
IR_Event_Code = IR_EVENT_TIME_3 ;
break;
case 0x354A: // filter reset
IR_Event_Code = IR_EVENT_FILTER_RESET;
break;
default:
IR_Event_Code = 0;
break;
}
if(IR_Event_Code)
{
IR_Event_Flag = 1;
}
*/
}
remocon_buff[0] = 0;
remocon_buff[1] = 0;
remocon_bit_count = 0;
remocon_pos = 0;
}
}
volatile uint8_t Touch_Event = 0;
void GPABC_IRQHandler(void)
{
uint32_t reg;
if(GPIO_GET_INT_FLAG(PB, BIT12))
{
GPIO_CLR_INT_FLAG(PB, BIT12);
CLK->WK_INTSTS = 1; /* clear interrupt status */
if(PB12 == 0)Touch_Event = 1;
else Touch_Event = 2;
}
else if(GPIO_GET_INT_FLAG(PB, BIT14))
{
GPIO_CLR_INT_FLAG(PB, BIT14);
CLK->WK_INTSTS = 1; /* clear interrupt status */
IR_Receive();
}
else
{
reg = PA->ISRC; PA->ISRC = reg;
reg = PB->ISRC; PB->ISRC = reg;
reg = PC->ISRC; PC->ISRC = reg;
}
}
volatile uint8_t Run_Timer = 0;
volatile uint16_t mSec_Timer = 0;
volatile uint16_t Blink_Timer = 0;
volatile uint8_t Rx_FND_TimeOut = 0;
volatile uint16_t FastBlink_Timer = 0;
void TMR0_IRQHandler(void)
{
if(Run_Timer)Run_Timer--;
if(mSec_Timer)mSec_Timer--;
if(Blink_Timer)Blink_Timer--;
if(FastBlink_Timer)FastBlink_Timer--;
if(Rx_FND_TimeOut)Rx_FND_TimeOut--;
// clear timer interrupt flag
TIMER_ClearIntFlag(TIMER0);
}
// TIMER_ClearWakeupFlag(TIMER0);
void Timer0_Init(void)
{
TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1000); // 1ms -> HZ
// Enable timer interrupt
TIMER_EnableInt(TIMER0);
NVIC_EnableIRQ(TMR0_IRQn);
// Start Timer 0
TIMER_Start(TIMER0);
}
void TMR1_IRQHandler(void)
{
// clear timer interrupt flag
TIMER_ClearIntFlag(TIMER1);
}
void Timer1_Init(void)
{
TIMER_Open(TIMER1, TIMER_PERIODIC_MODE, 100); // 10ms -> HZ
// Enable timer interrupt
TIMER_EnableInt(TIMER1);
NVIC_EnableIRQ(TMR1_IRQn);
// Start Timer 0
TIMER_Start(TIMER1);
}
void Timer2_Init(void) ///////////////////////////////////////////////////////////////////
{
TIMER_Open(TIMER2, TIMER_PERIODIC_MODE, 1); // 1000ms -> HZ
// Enable timer interrupt
TIMER_EnableInt(TIMER2);
// NVIC_EnableIRQ(TMR2_IRQn);
// Start Timer 0
TIMER_Start(TIMER2);
}/////////////////////////////////////////////////////////////////////////////////////
void PWM_Init(void)
{
// PWM0 frequency is 300Hz, duty 50%
// PWM_ConfigOutputChannel(PWM0, 3, 960, 50); // LCD Backlight
PWM_ConfigOutputChannel(PWM1, 0, 100, 0); // buzzer
// Enable output of all PWM channels
// PWM_EnableOutput(PWM0, 1<<3); // ch3
PWM_EnableOutput(PWM1, 0x01);
// Start
// PWM_Start(PWM0, 1<<3); // pwm0_ch3
PWM_Start(PWM1, 0x01);
}
volatile uint32_t ADC3_Value = 0;;
void ADC_IRQHandler(void)
{
uint32_t u32Flag;
// Get ADC conversion finish interrupt flag
u32Flag = ADC_GET_INT_FLAG(ADC, ADC_ADF_INT);
if(u32Flag & ADC_ADF_INT)
{
ADC3_Value = ADC_GET_CONVERSION_DATA(ADC, 3);
}
ADC_CLR_INT_FLAG(ADC, u32Flag);
}
void ADC_Init(void)
{
// Enable channel 1
ADC_Open(ADC, ADC_INPUT_MODE_SINGLE_END, ADC_OPERATION_MODE_SINGLE, ADC_CH_1_MASK);
// Set reference voltage to AVDD
ADC_SET_REF_VOLTAGE(ADC, ADC_REFSEL_POWER);
// Power on ADC
ADC_POWER_ON(ADC);
// Enable ADC ADC_IF interrupt
ADC_EnableInt(ADC, ADC_ADF_INT);
NVIC_EnableIRQ(ADC_IRQn);
ADC_START_CONV(ADC);
}
void GPIO_Init(void)
{
GPIO_SetMode(PA, BIT11, GPIO_PMD_OUTPUT); // ST
ST_LED = 0;
GPIO_SetMode(PA, BIT2|BIT3|BIT4, GPIO_PMD_OUTPUT); // A_2002
PA2 = 0;
PA3 = 0;
PA4 = 0;
GPIO_SetMode(PA, BIT1, GPIO_PMD_OUTPUT); // power
FND_POWER = 0;
}
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable clock source */
CLK_EnableXtalRC(CLK_PWRCTL_LIRC_EN_Msk|CLK_PWRCTL_HIRC_EN_Msk);
/* Waiting for clock source ready */
CLK_WaitClockReady(CLK_CLKSTATUS_LIRC_STB_Msk|CLK_CLKSTATUS_HIRC_STB_Msk);
/* If the defines do not exist in your project, please refer to the related clk.h in the Header folder appended to the tool package. */
/* Set HCLK clock */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_HCLK_CLK_DIVIDER(1));
/* Enable IP clock */
CLK_EnableModuleClock(GPIO_MODULE);
CLK_EnableModuleClock(WDT_MODULE);
// CLK_EnableModuleClock(I2C0_MODULE);
// CLK_EnableModuleClock(I2C1_MODULE);
// CLK_EnableModuleClock(PWM0_CH23_MODULE);
// CLK_EnableModuleClock(PWM1_CH01_MODULE);
CLK_EnableModuleClock(ISP_MODULE);
// CLK_EnableModuleClock(SC0_MODULE);
// CLK_EnableModuleClock(SC1_MODULE);
CLK_EnableModuleClock(SRAM_MODULE);
CLK_EnableModuleClock(TICK_MODULE);
CLK_EnableModuleClock(TMR0_MODULE);
CLK_EnableModuleClock(TMR1_MODULE);
CLK_EnableModuleClock(TMR2_MODULE);
CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(UART1_MODULE);
CLK_EnableModuleClock(WDT_MODULE);
/* Set IP clock */
// CLK_SetModuleClock(PWM0_CH23_MODULE, CLK_CLKSEL1_PWM0_CH23_S_HIRC, MODULE_NoMsk);
// CLK_SetModuleClock(PWM1_CH01_MODULE, CLK_CLKSEL2_PWM1_CH01_S_HIRC, MODULE_NoMsk);
// CLK_SetModuleClock(SC0_MODULE, CLK_CLKSEL2_SC_S_HIRC, CLK_SC0_CLK_DIVIDER(6));
// CLK_SetModuleClock(SC1_MODULE, CLK_CLKSEL2_SC_S_HIRC, CLK_SC1_CLK_DIVIDER(1));
CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0_S_HIRC, MODULE_NoMsk);
CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1_S_HIRC, MODULE_NoMsk);
CLK_SetModuleClock(TMR2_MODULE, CLK_CLKSEL2_TMR2_S_HIRC, MODULE_NoMsk);
CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_UART_CLK_DIVIDER(1));
CLK_SetModuleClock(UART1_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_UART_CLK_DIVIDER(1));
CLK_SetModuleClock(WDT_MODULE, 0, 0);
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
//If the defines do not exist in your project, please refer to the corresponding sys.h in the Header folder appended to the tool package.
SYS->PA_L_MFP = 0;//SYS_PA_L_MFP_PA5_MFP_ADC_CH5;
SYS->PA_H_MFP = 0;
SYS->PB_H_MFP = 0;
SYS->PB_L_MFP = SYS_PB_L_MFP_PB0_MFP_UART0_RX | SYS_PB_L_MFP_PB1_MFP_UART0_TX |SYS_PB_L_MFP_PB5_MFP_UART1_TX | SYS_PB_L_MFP_PB4_MFP_UART1_RX ;
SYS->PC_H_MFP = 0x00000000;
SYS->PC_L_MFP = 0x00000000;
SYS->PD_H_MFP = 0x00000000;
SYS->PD_L_MFP = 0x00000000;
SYS->PE_L_MFP = 0x00000000;
SYS->PF_L_MFP = SYS_PF_L_MFP_PF1_MFP_ICE_CLK | SYS_PF_L_MFP_PF0_MFP_ICE_DAT;
/* Lock protected registers */
SYS_LockReg();
return;
}
extern uint8_t Main_Modbus_ID;
void Processor_Init(void)
{
// 0 1 2 3 4 5 6 7 8 9 , ' ' , E , A
uint8_t eep_check[20];
uint8_t i;
Disp_Segdata(0, 8, 8, 8, 8);
Display_process();
delay_ms(2000);
Disp_Segdata(0, 16, 13, FND_VERSION>>4, FND_VERSION&0x0F); // R-01
Display_process();
delay_ms(2000);
////////////////////////////////////////////////////////////
for(i=0; i<10; i++)
{
Read_Data(i, &eep_check[i]);
}
if((eep_check[EEP_ADDR_START] == 0x55)&&(eep_check[EEP_ADDR_START+1] == 0xAA))
{
// Main_Modbus_ID = eep_check[EEP_ADDR_MODBUS_ID];
}
else
{
Write_Data(EEP_ADDR_START, 0x55);
Write_Data(EEP_ADDR_START+1, 0xAA);
// Write_Data(EEP_ADDR_MODBUS_ID, Main_Modbus_ID);
}
}
@@ -0,0 +1,733 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "Nano100Series.h"
#include "adc.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "uart.h"
#include "sys.h"
#include "clk.h"
#include "My_define.h"
extern volatile uint8_t Rx_rs485_TimeOut ;
extern volatile uint8_t Power_On;
extern volatile uint8_t Tx_Run_Mode;
extern volatile uint8_t Tx_Fan_Speed;
extern volatile uint8_t Tx_Reservation_Hour;
extern uint8_t Ventilation_SA[5];
extern uint8_t Ventilation_EA[5];
extern uint8_t AirClean_SA[5];
extern uint8_t AirClean_EA[5];
extern uint8_t Bypass_SA[5];
extern uint8_t Bypass_EA[5];
extern uint8_t Test_Mode_Step;
volatile uint8_t Tx_Data_Mode = TX_DATA_MODE_REQUEST1;
uint16_t Main_Err_Code = 0;
volatile uint16_t Update_Event = 0;
const unsigned char auchCRCHi[] = {
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40,
0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1,
0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0,
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40
} ;
// Table of CRC values for low-order byte
const unsigned char auchCRCLo[] = {
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06,
0x07, 0xC7, 0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD,
0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09,
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A,
0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC, 0x14, 0xD4,
0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3,
0xF2, 0x32, 0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4,
0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A,
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29,
0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF, 0x2D, 0xED,
0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60,
0x61, 0xA1, 0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67,
0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F,
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68,
0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA, 0xBE, 0x7E,
0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71,
0x70, 0xB0, 0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92,
0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C,
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B,
0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89, 0x4B, 0x8B,
0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42,
0x43, 0x83, 0x41, 0x81, 0x80, 0x40
} ;
uint16_t CRC16(uint8_t *puchMsg, uint16_t usDataLen)
{
uint8_t uchCRCHi = 0xFF ; // high CRC byte initialized
uint8_t uchCRCLo = 0xFF ; // low CRC byte initialized
uint8_t uIndex ; // will index into CRC lookup table
while (usDataLen--) // pass through message buffer
{
uIndex = uchCRCHi ^ *puchMsg++ ; // calculate the CRC
uchCRCHi = uchCRCLo ^ auchCRCHi[uIndex] ;
uchCRCLo = auchCRCLo[uIndex] ;
}
return ((uint16_t)uchCRCHi << 8 | (uint16_t)uchCRCLo) ;
}
uint16_t Aeverage_calculator(uint16_t val, uint16_t * array_val)
{
uint8_t i;
uint16_t max = 0;
uint16_t min = 10000;
uint32_t sum = 0;
uint16_t Rval = 0;
for(i=9; i>0; i--)
{
*(array_val+i) = *(array_val+i-1);
}
*array_val = val;
for(i=0; i<10; i++)
{
if(array_val[i] >= max)
{
max = array_val[i];
}
if(array_val[i] <= min)
{
min = array_val[i];
}
sum += array_val[i];
}
Rval = (uint16_t)((sum - max - min)/8);
return(Rval);
}
///////////////////////////////////////////////////////////////////////////////
////////////////////////////////
extern volatile uint8_t Rx_modbus_TimeOut;
void Rx_modbus_Check(uint8_t data)
{
}
void SC0_IRQHandler(void)
{
uint8_t data;
data = SCUART_READ(SC0);
Rx_modbus_Check(data);
Rx_modbus_TimeOut = 5;
return;
}
uint8_t Tx_rs485_buffer[25];
uint8_t Rx_rs485_buffer[25];
uint8_t Rx_rs485_Pos = 0;
volatile uint8_t Rx_rs485_complete = 0;
void Rx_rs485_Check(uint8_t data)
{
uint16_t cksum = 0, iTmp = 0;
if(Rx_rs485_TimeOut == 0)Rx_rs485_Pos = 0;
switch(Rx_rs485_Pos)
{
case 0:
if(data != 0xAA)break;
Rx_rs485_buffer[Rx_rs485_Pos++] = data;
break;
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
Rx_rs485_buffer[Rx_rs485_Pos++] = data;
break;
case 20:
Rx_rs485_buffer[Rx_rs485_Pos++] = data;
iTmp = (uint16_t)Rx_rs485_buffer[19]<<8;
cksum = iTmp + (uint16_t)Rx_rs485_buffer[20] ;
if(cksum == CRC16(Rx_rs485_buffer, 19))
{
Rx_rs485_complete = 1;
}
Rx_rs485_Pos = 0;
break;
default:
Rx_rs485_Pos = 0;
break;
}
}
extern uint8_t In_Com_Error_Count;
extern uint8_t Out_Com_Error_Count ;
extern uint8_t Sensor_Error_Count;
void com_rs485_process(void)
{
if(Rx_rs485_complete == 1)
{
Rx_rs485_complete = 0;
if(Rx_rs485_buffer[1] == 0x10)//main
{
Rx_Main_Parsing();
In_Com_Error_Count = 0;
Main_Err_Code &= ~ERROR_IN_COM;
}
else if(Rx_rs485_buffer[1] == 0x01)
{
if(Rx_rs485_buffer[2] == 1) // id 1 - sensor pack
{
Rx_Sensor_Parsing();
Sensor_Error_Count = 0;
Main_Err_Code &= ~(ERROR_CO2 | ERROR_DUST);
}
}
}
}
volatile uint8_t Filter_Reset_Flag = 0;
uint16_t Used_Filter_Time = 0;
uint16_t Used_Soja_Time = 0;
uint8_t Main_BxD_Version = 0;
int8_t Ex_Temperature = 0;
int8_t In_Temperature = 0;
uint16_t SA_rpm = 0, EA_rpm = 0;
uint8_t Vsp_Mode = 0;
uint8_t Wifi_Status = 0;
extern uint8_t Main_Modbus_ID;
uint8_t Main_BxD_FW_Version[3];
void Rx_Main_Parsing(void)
{
uint16_t Tmp_Err = 0;
if(Rx_rs485_buffer[2] != 0x00)return; // My id = 0
Vsp_Mode = Rx_rs485_buffer[3];
switch(Vsp_Mode)
{
case 0x00: // nomal mode
if(Rx_rs485_buffer[4] & 0x10)
{
Tx_Run_Mode = Rx_rs485_buffer[4]&0x0F;
if(Rx_rs485_buffer[4] == 0x10)
{
if((Power_On == 1)&&(Tx_Run_Mode == MODE_OFF))power_off_process();
}
else
{
if((Power_On == 0)&&(Tx_Run_Mode != MODE_OFF))power_on_process_by_roomcon();
}
}
if(Rx_rs485_buffer[5] & 0x10)Tx_Fan_Speed = Rx_rs485_buffer[5]&0x0F;
if(Rx_rs485_buffer[6] & 0x10)
{
Tx_Reservation_Hour = Rx_rs485_buffer[6]&0x0F;
}
Tmp_Err = (((uint16_t)Rx_rs485_buffer[7]<<8) |( (uint16_t)Rx_rs485_buffer[8]&0x00FF))&0x00FF;
Main_Err_Code &= ~0x00FF;
Main_Err_Code |= Tmp_Err;
if(Filter_Reset_Flag == 1)
{
if((Main_Err_Code&0x000F) == 0)Filter_Reset_Flag = 0;
}
Used_Filter_Time = ((uint16_t)Rx_rs485_buffer[11]<<8) |( (uint16_t)Rx_rs485_buffer[12]&0x00FF);
Used_Soja_Time = ((uint16_t)Rx_rs485_buffer[13]<<8) |( (uint16_t)Rx_rs485_buffer[14]&0x00FF);
Main_BxD_FW_Version[0] = Rx_rs485_buffer[15];
Main_BxD_FW_Version[1] = Rx_rs485_buffer[16];
Main_BxD_FW_Version[2] = Rx_rs485_buffer[17];
Wifi_Status = Rx_rs485_buffer[18];
break;
case 0x01: // vent request mode
Ventilation_SA[0] = Rx_rs485_buffer[4]; // VENT 1 SA
Ventilation_EA[0] = Rx_rs485_buffer[5]; // VENT 1 EA
Ventilation_SA[1] = Rx_rs485_buffer[6]; // VENT 2 SA
Ventilation_EA[1] = Rx_rs485_buffer[7]; // VENT 2 EA
Ventilation_SA[2] = Rx_rs485_buffer[8]; // VENT 3 SA
Ventilation_EA[2] = Rx_rs485_buffer[9];// VENT 3 EA
Ventilation_SA[3] = Rx_rs485_buffer[10]; // VENT 4 SA
Ventilation_EA[3] = Rx_rs485_buffer[11]; // VENT 4 EA
Ventilation_SA[4] = Rx_rs485_buffer[12]; // VENT 5 SA
Ventilation_EA[4] = Rx_rs485_buffer[13]; // VENT 6 EA
Main_Modbus_ID = Rx_rs485_buffer[14]; // Modbus set id
Tx_Data_Mode = TX_DATA_MODE_REQUEST2;
break;
case 0x02: // air request mode
AirClean_SA[0] = Rx_rs485_buffer[4]; // AIR 1 SA
AirClean_EA[0] = Rx_rs485_buffer[5]; // AIR 1 EA
AirClean_SA[1] = Rx_rs485_buffer[6]; // AIR 2 SA
AirClean_EA[1] = Rx_rs485_buffer[7]; // AIR 2 EA
AirClean_SA[2] = Rx_rs485_buffer[8]; // AIR 3 SA
AirClean_EA[2] = Rx_rs485_buffer[9];// AIR 3 EA
AirClean_SA[3] = Rx_rs485_buffer[10]; // AIR 4 SA
AirClean_EA[3] = Rx_rs485_buffer[11]; // AIR 4 EA
AirClean_SA[4] = Rx_rs485_buffer[12]; // AIR 5 SA
AirClean_EA[4] = Rx_rs485_buffer[13]; // AIR 6 EA
Tx_Data_Mode = TX_DATA_MODE_REQUEST3;
break;
case 0x03: // bypass request mode
Bypass_SA[0] = Rx_rs485_buffer[4]; // BY 1 SA
Bypass_EA[0] = Rx_rs485_buffer[5]; // BY 1 EA
Bypass_SA[1] = Rx_rs485_buffer[6]; // BY 2 SA
Bypass_EA[1] = Rx_rs485_buffer[7]; // BY 2 EA
Bypass_SA[2] = Rx_rs485_buffer[8]; // BY 3 SA
Bypass_EA[2] = Rx_rs485_buffer[9];// BY 3 EA
Bypass_SA[3] = Rx_rs485_buffer[10]; // BY 4 SA
Bypass_EA[3] = Rx_rs485_buffer[11]; // BY 4 EA
Bypass_SA[4] = Rx_rs485_buffer[12]; // BY 5 SA
Bypass_EA[4] = Rx_rs485_buffer[13]; // BY 6 EA
Tx_Data_Mode = TX_DATA_MODE_NORMAL;
break;
case 0x10:
SA_rpm = ((uint16_t)Rx_rs485_buffer[10]<<8) |( (uint16_t)Rx_rs485_buffer[11]&0x00FF);
EA_rpm = ((uint16_t)Rx_rs485_buffer[12]<<8) |( (uint16_t)Rx_rs485_buffer[13]&0x00FF);
break;
default:
Tx_Data_Mode = TX_DATA_MODE_NORMAL;
break;
}
Tx_Main_process();
}
uint8_t CheckSum_Creator(uint8_t *buf, uint8_t len)
{
uint8_t i, rt;
rt = 0;
for(i=0; i<len; i++)
{
rt ^= buf[i];
}
return(rt);
}
extern volatile uint8_t Tx_Mode_Event, Tx_Fan_Event, Tx_Reserve_Event;
extern uint8_t Wifi_Command ;
void Tx_Main_process(void)
{
uint16_t cksum = 0;
uint8_t i = 0;
for(i=0; i<20; i++)Tx_rs485_buffer[i] = 0;
Tx_rs485_buffer[0] = 0xAA;
Tx_rs485_buffer[1] = 0x01;
Tx_rs485_buffer[2] = 0x00; // ID = 0
Tx_rs485_buffer[3] = Tx_Data_Mode;
switch(Tx_Data_Mode)
{
case TX_DATA_MODE_NORMAL:
Tx_rs485_buffer[4] = Tx_Run_Mode|Tx_Mode_Event;
Tx_rs485_buffer[5] = Tx_Fan_Speed|Tx_Fan_Event;
Tx_rs485_buffer[6] = Tx_Reservation_Hour|Tx_Reserve_Event;
Tx_Mode_Event = 0;
Tx_Fan_Event = 0;
Tx_Reserve_Event = 0;
Tx_rs485_buffer[7] = 0x00;
Tx_rs485_buffer[8] = Filter_Reset_Flag;
Tx_rs485_buffer[9] = 0;//(signed char)Out_Temperature;
Tx_rs485_buffer[10] = 0;//(signed char)In_Temperature;
Tx_rs485_buffer[11] = (uint8_t)(Used_Filter_Time>>8);
Tx_rs485_buffer[12] = (uint8_t)(Used_Filter_Time&0x00FF);
Tx_rs485_buffer[13] = (uint8_t)(Used_Soja_Time>>8);
Tx_rs485_buffer[14] = (uint8_t)(Used_Soja_Time&0x00FF);
Tx_rs485_buffer[15] = 'S';
Tx_rs485_buffer[16] = 'I';
Tx_rs485_buffer[17] = ROOMCON_FW_VERSION;
Tx_rs485_buffer[18] = Wifi_Command;
Wifi_Command = 0;
break;
case TX_DATA_MODE_REQUEST1:
break;
case TX_DATA_MODE_REQUEST2:
break;
case TX_DATA_MODE_REQUEST3:
break;
case TX_DATA_MODE_SETTING:
Tx_rs485_buffer[4] = Test_Mode_Step;
switch(Test_Mode_Step)
{
case 0x01:
Tx_rs485_buffer[5] = Ventilation_SA[0];
Tx_rs485_buffer[6] = Ventilation_EA[0];
break;
case 0x02:
Tx_rs485_buffer[5] = Ventilation_SA[1];
Tx_rs485_buffer[6] = Ventilation_EA[1];
break;
case 0x03:
Tx_rs485_buffer[5] = Ventilation_SA[2];
Tx_rs485_buffer[6] = Ventilation_EA[2];
break;
case 0x04:
Tx_rs485_buffer[5] = Ventilation_SA[3];
Tx_rs485_buffer[6] = Ventilation_EA[3];
break;
case 0x05:
Tx_rs485_buffer[5] = Ventilation_SA[4];
Tx_rs485_buffer[6] = Ventilation_EA[4];
break;
case 0x06:
Tx_rs485_buffer[5] = AirClean_SA[0];
Tx_rs485_buffer[6] = AirClean_EA[0];
break;
case 0x07:
Tx_rs485_buffer[5] = AirClean_SA[1];
Tx_rs485_buffer[6] = AirClean_EA[1];
break;
case 0x08:
Tx_rs485_buffer[5] = AirClean_SA[2];
Tx_rs485_buffer[6] = AirClean_EA[2];
break;
case 0x09:
Tx_rs485_buffer[5] = AirClean_SA[3];
Tx_rs485_buffer[6] = AirClean_EA[3];
break;
case 0x0A:
Tx_rs485_buffer[5] = AirClean_SA[4];
Tx_rs485_buffer[6] = AirClean_EA[4];
break;
case 0x0B:
Tx_rs485_buffer[5] = Bypass_SA[0];
Tx_rs485_buffer[6] = Bypass_EA[0];
break;
case 0x0C:
Tx_rs485_buffer[5] = Bypass_SA[1];
Tx_rs485_buffer[6] = Bypass_EA[1];
break;
case 0x0D:
Tx_rs485_buffer[5] = Bypass_SA[2];
Tx_rs485_buffer[6] = Bypass_EA[2];
break;
case 0x0E:
Tx_rs485_buffer[5] = Bypass_SA[3];
Tx_rs485_buffer[6] = Bypass_EA[3];
break;
case 0x0F:
Tx_rs485_buffer[5] = Bypass_SA[4];
Tx_rs485_buffer[6] = Bypass_EA[4];
break;
case 0x10:
Tx_rs485_buffer[5] = Main_Modbus_ID;
Tx_rs485_buffer[6] = 0;
break;
default:
break;
}
break;
default:
break;
}
cksum = CRC16(Tx_rs485_buffer, 19) ;
Tx_rs485_buffer[19] = (uint8_t)(cksum>>8) ;
Tx_rs485_buffer[20] = (uint8_t)cksum & 0x00FF ;
delay_ms(1);
PB6 = 1; // DIR
UART_Write(UART1, Tx_rs485_buffer, 21);
while ( !(UART1->FSR & UART_FSR_TX_EMPTY_F_Msk) );
while ( !(UART1->FSR & UART_FSR_TE_F_Msk) );
PB6 = 0; // DIR
}
void UART1_HANDLE() // modbus
{
uint8_t u8InChar=0xFF;
uint32_t u32IntSts= UART1->ISR;
if(u32IntSts & UART_ISR_RDA_IS_Msk)
{
u8InChar = UART_READ(UART1); /* Rx trigger level is 1 byte*/
Rx_rs485_Check(u8InChar);
Rx_rs485_TimeOut = 5;
}
if(u32IntSts & UART_ISR_THRE_IS_Msk)
{
;
}
}
void UART1_IRQHandler(void) // modbus
{
UART1_HANDLE();
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////
uint16_t CO2_Value = 0;
uint16_t Pm_1_0_value = 0;
uint16_t Pm_2_5_value = 0;
uint16_t Pm_10_value = 0;
signed int temperature_val = 0, humidity_val = 0;
signed int tvoc_val = 0;
uint8_t Sensor_BxD_Version = 0;
extern uint8_t IR_Event_Code;
extern volatile uint8_t IR_Event_Flag;
void Rx_Sensor_Parsing(void)
{
uint16_t iTmp, cksum;
uint8_t Sensor_id = 0;
uint16_t temp_pm10 = 0;
uint16_t temp_pm2_5 = 0;
uint16_t temp_pm1_0 = 0;
uint16_t temp_co2 = 0;
uint16_t temp_humi = 0;
uint16_t temp_temp = 0; // signed
uint16_t temp_voc = 0;
iTmp = (uint16_t)Rx_rs485_buffer[19]<<8;
cksum = iTmp + (uint16_t)Rx_rs485_buffer[20] ;
if(cksum != CRC16(Rx_rs485_buffer, 19))return;
temp_pm10 = (uint16_t)Rx_rs485_buffer[3]<<8;
temp_pm10 += (uint16_t)Rx_rs485_buffer[4];
temp_pm2_5 = (uint16_t)Rx_rs485_buffer[5]<<8;
temp_pm2_5 += (uint16_t)Rx_rs485_buffer[6];
temp_pm1_0 = (uint16_t)Rx_rs485_buffer[7]<<8;
temp_pm1_0 += (uint16_t)Rx_rs485_buffer[8];
temp_co2 = (uint16_t)Rx_rs485_buffer[9]<<8;
temp_co2 += (uint16_t)Rx_rs485_buffer[10];
temp_humi = (uint16_t)Rx_rs485_buffer[11]<<8;
temp_humi += (uint16_t)Rx_rs485_buffer[12];
temp_temp = (uint16_t)Rx_rs485_buffer[13]<<8;
temp_temp += (uint16_t)Rx_rs485_buffer[14];
temp_voc = (uint16_t)Rx_rs485_buffer[15]<<8;
temp_voc += (uint16_t)Rx_rs485_buffer[16];
IR_Event_Code = Rx_rs485_buffer[18];
if(IR_Event_Code)IR_Event_Flag = 1;
Pm_10_value = temp_pm10;
Pm_2_5_value = temp_pm2_5;
Pm_1_0_value = temp_pm1_0;
CO2_Value = temp_co2;
if(temp_temp & 0x8000)
{
temp_temp &= ~0x8000;
temperature_val = (signed int)temp_temp * -1;
}
else
{
temperature_val = (signed int)temp_temp;
}
humidity_val = (signed int)temp_humi;
tvoc_val = (signed int)temp_voc;
}
void UART0_HANDLE() // co2
{
uint8_t u8InChar=0xFF;
uint32_t u32IntSts= UART0->ISR;
if(u32IntSts & UART_ISR_RDA_IS_Msk)
{
u8InChar = UART_READ(UART0); /* Rx trigger level is 1 byte*/
}
if(u32IntSts & UART_ISR_THRE_IS_Msk)
{
;
}
}
void UART0_IRQHandler(void) // co2
{
UART0_HANDLE();
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////
void Tx_modbus_process(void)
{
uint16_t i;
for(i=0; i<7; i++)
{
//UART_WRITE(UART1, Tx_modbus_Buff[i]);
}
}
///////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////
extern volatile uint8_t Rx_wifi_TimeOut;
volatile uint8_t Rx_wifi_complete = 0;
uint8_t Rx_wifi_buffer[40];
uint8_t Tx_wifi_buffer[40];
uint8_t Rx_wifi_Pos = 0;
void Rx_wifi_Check(uint8_t data)
{
if(Rx_wifi_TimeOut == 0)Rx_wifi_Pos = 0;
switch(Rx_wifi_Pos)
{
case 0:
if(data != 0x42){Rx_wifi_Pos = 0;break;}
Rx_wifi_buffer[Rx_wifi_Pos++]=data;
break;
case 31:
Rx_wifi_buffer[Rx_wifi_Pos]=data;
Rx_wifi_complete = 1;
Rx_wifi_Pos = 0;
break;
default:
Rx_wifi_buffer[Rx_wifi_Pos++] = data;
break;
}
}
void Tx_wifi_data(uint8_t *buf, uint8_t Len)
{
SCUART_Write(SC1, buf, Len);
}
void SC1_IRQHandler(void) // wifi
{
uint8_t data;
data = SCUART_READ(SC1);
Rx_wifi_Check(data);
Rx_wifi_TimeOut = 5;
return;
}
void Rx_wifi_Parsing(void)
{
;
}
void tx_wifi_data(void)
{
Tx_wifi_buffer[0] = 0x11;
Tx_wifi_buffer[1] = 0x02;
Tx_wifi_buffer[2] = 0x0B;
Tx_wifi_buffer[3] = 0x07;
Tx_wifi_buffer[4] = 0xDB;
Tx_wifi_data(Tx_wifi_buffer, 5);
}
@@ -0,0 +1,128 @@
void Display_update(void);
void Display_process(void);
void Initial_Signal();
void Disp_Segdata(uint8_t Sel, uint8_t digit4,uint8_t digit3, uint8_t digit2, uint8_t digit1);
void Led_OnOff(uint8_t kind, uint8_t onoff);
void delay_ms(uint32_t ms);
void delay_us(uint32_t us);
void PowerDownFunction(void);
void GPIO_Init(void);
void PWM_Init(void);
void Timer0_Init(void);
void Timer1_Init(void);
void Timer2_Init(void);
void SYS_Init(void);
void UART0_Init(void);
void UART1_Init(void);
void SC0_Init();
void SC1_Init();
void ADC_Init(void);
void Processor_Init(void);
void Error_process(void);
void Test_exit_process(void);
void Test_vsp_into_process(void);
void Touch_process(void);
void power_off_process(void);
void power_on_process(void);
void power_on_process_by_roomcon(void); //iot
void power_off_process_by_roomcon(void);
void IR_Remocon_process(void);
extern uint8_t touch_i2c_read(uint8_t index, uint8_t *value);
extern uint8_t touch_i2c_write(uint8_t index, uint8_t d);
extern void touch_i2c_init();
extern void Melody_process(void);
void Air_Quality_process(void);
void com_rs485_process(void);
void Tx_Main_process(void);
void Rx_rs485_Check(uint8_t data);
void Rx_Main_Parsing(void);
void Rx_Sensor_Parsing(void);
void Rx_wifi_Check(uint8_t data);
void Rx_wifi_Parsing(void);
uint8_t CheckSum_Creator(uint8_t *buf, uint8_t len);
#define TX_EVENT 0x10
#define MELODY_OFF 0
#define MELODY_POWER_ON 1
#define MELODY_POWER_OFF 2
#define MELODY_TOUCH 3
#define MELODY_NG 4
#define MODE_OFF 0
#define MODE_VENT 1
#define MODE_AUTO 2
#define MODE_AIR_CLEAN 3
#define MODE_BYPASS 4
#define ERROR_SA 0x0040
#define ERROR_EA 0x0080
#define ERROR_FILTER_CLEAN 0x0001 // FILTER & SOJA
#define ERROR_FILTER_CHANGE 0x0002
#define ERROR_SOJA_CHANGE 0x0004
#define ERROR_IN_COM 0x0010
#define ERROR_OUT_COM 0x0020
#define ERROR_TEMP 0x0800
#define ERROR_HUMI 0x1000
#define ERROR_TVOC 0x2000
#define ERROR_DUST 0x4000
#define ERROR_CO2 0x8000
#define EVENT_POWER 0x01
#define EVENT_MODE 0x02
#define EVENT_WIND 0x04
#define EVENT_TIME 0x08
#define TX_DATA_MODE_NORMAL 0x00
#define TX_DATA_MODE_REQUEST1 0x01
#define TX_DATA_MODE_REQUEST2 0x02
#define TX_DATA_MODE_REQUEST3 0x03
#define TX_DATA_MODE_SETTING 0x10
#define ROOMCON_VERSION 0x01
#define CO2_VERSION 0x01
#define EEP_ADDR_START 0x01
#define EEP_ADDR_MODBUS_ID 0x05
// S1000
#define WIND_CMH_0 0
#define WIND_CMH_1 400
#define WIND_CMH_2 750
#define WIND_CMH_3 1000
#define ROOMCON_FW_VERSION 22
extern uint8_t Main_BxD_FW_Version[3];
extern uint8_t Sensor_BxD_Version;
@@ -0,0 +1,55 @@
void Display_update(void);
void Display_process(void);
void Initial_Signal();
void Disp_Segdata(uint8_t Sel, uint8_t digit4,uint8_t digit3, uint8_t digit2, uint8_t digit1);
void Led_OnOff(uint8_t kind, uint8_t onoff);
void delay_ms(uint32_t ms);
void delay_us(uint32_t us);
void PowerDownFunction(void);
void GPIO_Init(void);
void PWM_Init(void);
void Timer0_Init(void);
void Timer1_Init(void);
void Timer2_Init(void);
void SYS_Init(void);
void UART0_Init(void);
void UART1_Init(void);
void SC0_Init();
void SC1_Init();
void ADC_Init(void);
void Processor_Init(void);
void Error_process(void);
#define ST_LED PA11
#define IN485_DIR PB6
#define FND_POWER PA1
#define FND_VERSION 1
extern uint16_t SEN66_pm10p0;
extern uint16_t SEN66_pm4p0;
extern uint16_t SEN66_pm2p5;
extern uint16_t SEN66_pm1p0;
extern uint16_t SEN66_humidity_value;
extern uint16_t SEN66_temperature_value;
extern uint16_t SEN66_VOC_value;
extern uint16_t SEN66_NOx_value;
extern uint16_t SEN66_CO2_value;
extern volatile uint8_t Run_Timer;
extern volatile uint16_t mSec_Timer;
extern volatile uint16_t Blink_Timer;
extern volatile uint8_t Rx_FND_TimeOut;
extern volatile uint16_t FastBlink_Timer;
@@ -0,0 +1,749 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "Nano100Series.h"
#include "adc.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "uart.h"
#include "sys.h"
#include "clk.h"
#include "EEPROM_Emulate.h"
#include "My_define.h"
extern uint8_t Melody_Mode;
extern volatile uint8_t Power_On;
extern volatile uint8_t Tx_Run_Mode;
extern volatile uint8_t Tx_Fan_Speed;
extern volatile uint8_t Tx_Reservation_Hour;
extern uint16_t Main_Err_Code;
extern uint8_t Vsp_Mode;
void delay_us(uint32_t us)
{
CLK_SysTickDelay(us);
}
void delay_ms(uint32_t ms)
{
while(ms--)
{
delay_us(1000);
}
}
void UART0_Init()//co2
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
SYS_ResetModule(UART0_RST);
UART_Open(UART0, 115200);
UART_EnableInt(UART0, UART_IER_RDA_IE_Msk);
NVIC_EnableIRQ(UART0_IRQn);
}
void UART1_Init()
{
/*---------------------------------------------------------------------------------------------------------*/
/* Init UART */
/*---------------------------------------------------------------------------------------------------------*/
SYS_ResetModule(UART1_RST);
UART_Open(UART1, 115200);
UART_EnableInt(UART1, UART_IER_RDA_IE_Msk);
NVIC_EnableIRQ(UART1_IRQn);
}
void SC0_Init() // to main
{
SCUART_Open(SC0, 1200);
// Enable smartcard receive interrupt
SCUART_ENABLE_INT(SC0, SC_IER_RDA_IE_Msk);
NVIC_EnableIRQ(SC0_IRQn);
}
void SC1_Init() // to dust
{
SCUART_Open(SC1, 9600);
// Enable smartcard receive interrupt
SCUART_ENABLE_INT(SC1, SC_IER_RDA_IE_Msk);
NVIC_EnableIRQ(SC1_IRQn);
}
void PowerDownFunction(void)
{
;
}
#define IR_EVENT_POWER 0x01
#define IR_EVENT_MODE 0x02
#define IR_EVENT_WIND_UP 0x04
#define IR_EVENT_WIND_DN 0x05
#define IR_EVENT_TIME_1 0x06
#define IR_EVENT_TIME_2 0x07
#define IR_EVENT_TIME_3 0x08
#define IR_EVENT_FILTER_RESET 0x09
#define IR_START 13500
#define IR_HIGH 2260
#define IR_LOW 1180
#define IR_STOP 600
#define IR_REPEAT 11200
uint16_t long_timer1 = 0;
uint16_t remocon_buff[4];
uint8_t remocon_pos = 0;
uint8_t remocon_bit_count = 0;
uint8_t IR_Event_Code = 0;
volatile uint8_t IR_Event_Flag = 0;
void IR_Receive(void)
{
uint16_t tmp = 0;
long_timer1 = TIMER2->DR/12;
TIMER2->CTL |= TIMER_CTL_SW_RST_Msk;
TIMER_Start(TIMER2);
if((long_timer1 > IR_START-300)&&(long_timer1 < IR_START+300))
{
remocon_buff[0] = 0;
remocon_buff[1] = 0;
remocon_bit_count = 0;
remocon_pos = 0;
}
else if((long_timer1 > IR_REPEAT-300)&&(long_timer1 < IR_REPEAT+300))
{
remocon_buff[0] = 0;
remocon_buff[1] = 0;
remocon_bit_count = 0;
remocon_pos = 0;
}
else if((long_timer1 > IR_HIGH-200)&&(long_timer1 < IR_HIGH+200))
{
remocon_buff[remocon_pos] |= 0x8000;
if(remocon_bit_count++ >= 15){remocon_bit_count = 0;remocon_pos=1;}
else {remocon_buff[remocon_pos] >>= 1;}
}
else if((long_timer1 > IR_LOW-200)&&(long_timer1 < IR_LOW+200))
{
remocon_buff[remocon_pos] &= ~0x8000;
if(remocon_bit_count++ >= 15){remocon_bit_count = 0;remocon_pos=1;}
else {remocon_buff[remocon_pos] >>= 1;}
}
if((remocon_pos == 1)&&(remocon_bit_count == 15))
{
if(remocon_buff[0] == 0xA55A)
{
tmp = remocon_buff[1];
/* switch(tmp)
{
case 0x6E11: // Power
IR_Event_Code = IR_EVENT_POWER;
break;
case 0x6D12: // mode
IR_Event_Code = IR_EVENT_MODE;
break;
case 0x6C13: // up
IR_Event_Code = IR_EVENT_WIND_UP;
break;
case 0x6817: // dn
IR_Event_Code = IR_EVENT_WIND_DN;
break;
case 0x6718: // 1hour
IR_Event_Code = IR_EVENT_TIME_1 ;
break;
case 0x6619: // 2hour
IR_Event_Code = IR_EVENT_TIME_2 ;
break;
case 0x215E: // 3hour
IR_Event_Code = IR_EVENT_TIME_3 ;
break;
case 0x354A: // filter reset
IR_Event_Code = IR_EVENT_FILTER_RESET;
break;
default:
IR_Event_Code = 0;
break;
}
if(IR_Event_Code)
{
IR_Event_Flag = 1;
}
*/
}
remocon_buff[0] = 0;
remocon_buff[1] = 0;
remocon_bit_count = 0;
remocon_pos = 0;
}
}
volatile uint8_t Touch_Event = 0;
void GPABC_IRQHandler(void)
{
uint32_t reg;
if(GPIO_GET_INT_FLAG(PB, BIT12))
{
GPIO_CLR_INT_FLAG(PB, BIT12);
CLK->WK_INTSTS = 1; /* clear interrupt status */
if(PB12 == 0)Touch_Event = 1;
else Touch_Event = 2;
}
else if(GPIO_GET_INT_FLAG(PB, BIT14))
{
GPIO_CLR_INT_FLAG(PB, BIT14);
CLK->WK_INTSTS = 1; /* clear interrupt status */
IR_Receive();
}
else
{
reg = PA->ISRC; PA->ISRC = reg;
reg = PB->ISRC; PB->ISRC = reg;
reg = PC->ISRC; PC->ISRC = reg;
}
}
volatile uint8_t Run_Timer = 0;
volatile uint16_t mSec_Timer = 0;
volatile uint16_t Touch_Event_Timer = 0;
volatile uint16_t Blink_Timer = 0;
volatile uint8_t Rx_rs485_TimeOut = 0;
volatile uint8_t Rx_modbus_TimeOut = 0;
volatile uint8_t Rx_wifi_TimeOut = 0;
volatile uint16_t FastBlink_Timer = 0;
void TMR0_IRQHandler(void)
{
Touch_Event_Timer++;
if(Run_Timer)Run_Timer--;
if(mSec_Timer)mSec_Timer--;
if(Blink_Timer)Blink_Timer--;
if(FastBlink_Timer)FastBlink_Timer--;
if(Rx_rs485_TimeOut)Rx_rs485_TimeOut--;
if(Rx_modbus_TimeOut)Rx_modbus_TimeOut--;
if(Rx_wifi_TimeOut)Rx_wifi_TimeOut--;
// clear timer interrupt flag
TIMER_ClearIntFlag(TIMER0);
}
// TIMER_ClearWakeupFlag(TIMER0);
void Timer0_Init(void)
{
TIMER_Open(TIMER0, TIMER_PERIODIC_MODE, 1000); // 1ms -> HZ
// Enable timer interrupt
TIMER_EnableInt(TIMER0);
NVIC_EnableIRQ(TMR0_IRQn);
// Start Timer 0
TIMER_Start(TIMER0);
}
void TMR1_IRQHandler(void)
{
Melody_process();
// clear timer interrupt flag
TIMER_ClearIntFlag(TIMER1);
}
void Timer1_Init(void)
{
TIMER_Open(TIMER1, TIMER_PERIODIC_MODE, 100); // 10ms -> HZ
// Enable timer interrupt
TIMER_EnableInt(TIMER1);
NVIC_EnableIRQ(TMR1_IRQn);
// Start Timer 0
TIMER_Start(TIMER1);
}
void Timer2_Init(void) ///////////////////////////////////////////////////////////////////
{
TIMER_Open(TIMER2, TIMER_PERIODIC_MODE, 1); // 1000ms -> HZ
// Enable timer interrupt
TIMER_EnableInt(TIMER2);
// NVIC_EnableIRQ(TMR2_IRQn);
// Start Timer 0
TIMER_Start(TIMER2);
}/////////////////////////////////////////////////////////////////////////////////////
void PWM_Init(void)
{
// PWM0 frequency is 300Hz, duty 50%
// PWM_ConfigOutputChannel(PWM0, 3, 960, 50); // LCD Backlight
PWM_ConfigOutputChannel(PWM1, 0, 100, 0); // buzzer
// Enable output of all PWM channels
// PWM_EnableOutput(PWM0, 1<<3); // ch3
PWM_EnableOutput(PWM1, 0x01);
// Start
// PWM_Start(PWM0, 1<<3); // pwm0_ch3
PWM_Start(PWM1, 0x01);
}
volatile uint32_t ADC3_Value = 0;;
void ADC_IRQHandler(void)
{
uint32_t u32Flag;
// Get ADC conversion finish interrupt flag
u32Flag = ADC_GET_INT_FLAG(ADC, ADC_ADF_INT);
if(u32Flag & ADC_ADF_INT)
{
ADC3_Value = ADC_GET_CONVERSION_DATA(ADC, 3);
}
ADC_CLR_INT_FLAG(ADC, u32Flag);
}
void ADC_Init(void)
{
// Enable channel 1
ADC_Open(ADC, ADC_INPUT_MODE_SINGLE_END, ADC_OPERATION_MODE_SINGLE, ADC_CH_1_MASK);
// Set reference voltage to AVDD
ADC_SET_REF_VOLTAGE(ADC, ADC_REFSEL_POWER);
// Power on ADC
ADC_POWER_ON(ADC);
// Enable ADC ADC_IF interrupt
ADC_EnableInt(ADC, ADC_ADF_INT);
NVIC_EnableIRQ(ADC_IRQn);
ADC_START_CONV(ADC);
}
void GPIO_Init(void)
{
GPIO_SetMode(PA, BIT2|BIT3|BIT4, GPIO_PMD_OUTPUT); // A_2002
PA2 = 0;
PA3 = 0;
PA4 = 0;
GPIO_SetMode(PA, BIT13|BIT14|BIT15, GPIO_PMD_OUTPUT); // B_2002
PA13 = 0;
PA14 = 0;
PA15 = 0;
GPIO_SetMode(PC, BIT9|BIT10|BIT11, GPIO_PMD_OUTPUT); // C_2002
PC9 = 0;
PC10 = 0;
PC11 = 0;
GPIO_SetMode(PD, BIT7|BIT14|BIT15, GPIO_PMD_OUTPUT); // D_2002
PD7 = 0;
PD14 = 0;
PD15 = 0;
GPIO_SetMode(PB, BIT6, GPIO_PMD_OUTPUT); // 485 DIR
PB6 = 0;
GPIO_SetMode(PA, BIT10, GPIO_PMD_OPEN_DRAIN); // touch
GPIO_SetMode(PA, BIT11, GPIO_PMD_OPEN_DRAIN);
GPIO_SetMode(PB, BIT12, GPIO_PMD_INPUT); // touch int
GPIO_ENABLE_PULL_UP(PB, BIT12);
GPIO_EnableInt(PB, 12, GPIO_INT_BOTH_EDGE);
GPIO_SetMode(PB, BIT14, GPIO_PMD_INPUT); // ir int
GPIO_ENABLE_PULL_UP(PB, BIT14);
GPIO_EnableInt(PB, 14, GPIO_INT_FALLING);
NVIC_EnableIRQ(GPABC_IRQn);
/* Enable interrupt de-bounce function and select de-bounce sampling cycle time */
GPIO_SET_DEBOUNCE_TIME(GPIO_DBCLKSRC_HCLK, GPIO_DBCLKSEL_1);
GPIO_ENABLE_DEBOUNCE(PB, BIT12|BIT14);
}
void SYS_Init(void)
{
/* Unlock protected registers */
SYS_UnlockReg();
/* Enable clock source */
CLK_EnableXtalRC(CLK_PWRCTL_LIRC_EN_Msk|CLK_PWRCTL_HIRC_EN_Msk);
/* Waiting for clock source ready */
CLK_WaitClockReady(CLK_CLKSTATUS_LIRC_STB_Msk|CLK_CLKSTATUS_HIRC_STB_Msk);
/* If the defines do not exist in your project, please refer to the related clk.h in the Header folder appended to the tool package. */
/* Set HCLK clock */
CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_HIRC, CLK_HCLK_CLK_DIVIDER(1));
/* Enable IP clock */
CLK_EnableModuleClock(GPIO_MODULE);
CLK_EnableModuleClock(WDT_MODULE);
// CLK_EnableModuleClock(I2C0_MODULE);
// CLK_EnableModuleClock(I2C1_MODULE);
// CLK_EnableModuleClock(PWM0_CH23_MODULE);
CLK_EnableModuleClock(PWM1_CH01_MODULE);
CLK_EnableModuleClock(ISP_MODULE);
CLK_EnableModuleClock(SC0_MODULE);
// CLK_EnableModuleClock(SC1_MODULE);
CLK_EnableModuleClock(SRAM_MODULE);
CLK_EnableModuleClock(TICK_MODULE);
CLK_EnableModuleClock(TMR0_MODULE);
CLK_EnableModuleClock(TMR1_MODULE);
CLK_EnableModuleClock(TMR2_MODULE);
// CLK_EnableModuleClock(UART0_MODULE);
CLK_EnableModuleClock(UART1_MODULE);
CLK_EnableModuleClock(WDT_MODULE);
/* Set IP clock */
// CLK_SetModuleClock(PWM0_CH23_MODULE, CLK_CLKSEL1_PWM0_CH23_S_HIRC, MODULE_NoMsk);
CLK_SetModuleClock(PWM1_CH01_MODULE, CLK_CLKSEL2_PWM1_CH01_S_HIRC, MODULE_NoMsk);
CLK_SetModuleClock(SC0_MODULE, CLK_CLKSEL2_SC_S_HIRC, CLK_SC0_CLK_DIVIDER(6));
// CLK_SetModuleClock(SC1_MODULE, CLK_CLKSEL2_SC_S_HIRC, CLK_SC1_CLK_DIVIDER(1));
CLK_SetModuleClock(TMR0_MODULE, CLK_CLKSEL1_TMR0_S_HIRC, MODULE_NoMsk);
CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1_S_HIRC, MODULE_NoMsk);
CLK_SetModuleClock(TMR2_MODULE, CLK_CLKSEL2_TMR2_S_HIRC, MODULE_NoMsk);
// CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_UART_CLK_DIVIDER(1));
CLK_SetModuleClock(UART1_MODULE, CLK_CLKSEL1_UART_S_HIRC, CLK_UART_CLK_DIVIDER(1));
CLK_SetModuleClock(WDT_MODULE, 0, 0);
/* Update System Core Clock */
/* User can use SystemCoreClockUpdate() to calculate SystemCoreClock. */
SystemCoreClockUpdate();
//If the defines do not exist in your project, please refer to the corresponding sys.h in the Header folder appended to the tool package.
SYS->PA_H_MFP = SYS_PA_H_MFP_PA9_MFP_SC0_DAT | SYS_PA_H_MFP_PA8_MFP_SC0_CLK;
SYS->PB_H_MFP = SYS_PB_H_MFP_PB11_MFP_PWM1_CH0;
SYS->PB_L_MFP = SYS_PB_L_MFP_PB5_MFP_UART1_TX | SYS_PB_L_MFP_PB4_MFP_UART1_RX ;
SYS->PC_H_MFP = 0x00000000;
SYS->PC_L_MFP = 0x00000000;
SYS->PD_H_MFP = 0x00000000;
SYS->PD_L_MFP = 0x00000000;
SYS->PE_L_MFP = 0x00000000;
SYS->PF_L_MFP = SYS_PF_L_MFP_PF1_MFP_ICE_CLK | SYS_PF_L_MFP_PF0_MFP_ICE_DAT;
/* Lock protected registers */
SYS_LockReg();
return;
}
extern uint8_t Main_Modbus_ID;
void Processor_Init(void)
{
// 0 1 2 3 4 5 6 7 8 9 , ' ' , E , A
uint8_t eep_check[20];
uint8_t i;
Power_On = 0;
Tx_Run_Mode = 0;
Tx_Fan_Speed = 0;
Tx_Reservation_Hour = 0;
Led_OnOff(100,1);//all on
Disp_Segdata(0, 8, 8, 8, 8);
Disp_Segdata(1, 8, 8, 8, 8);
Disp_Segdata(2, 8, 8, 8, 8);
for(i=0; i<10; i++)Display_process();
touch_i2c_init() ;
Melody_Mode = MELODY_TOUCH;
delay_ms(2000);
Led_OnOff(100, 0); // all off
Disp_Segdata(0, 14, 14, 5, 2); // s2
Disp_Segdata(1, 1, 0, 0, 0); // 1000
Disp_Segdata(2, 16, 13, ROOMCON_VERSION>>4, ROOMCON_VERSION&0x0F); // R-01
for(i=0; i<10; i++)Display_process();
delay_ms(2000);
power_off_process();
////////////////////////////////////////////////////////////
for(i=0; i<10; i++)
{
Read_Data(i, &eep_check[i]);
}
if((eep_check[EEP_ADDR_START] == 0x55)&&(eep_check[EEP_ADDR_START+1] == 0xAA))
{
// Main_Modbus_ID = eep_check[EEP_ADDR_MODBUS_ID];
}
else
{
Main_Modbus_ID = 1;
Write_Data(EEP_ADDR_START, 0x55);
Write_Data(EEP_ADDR_START+1, 0xAA);
// Write_Data(EEP_ADDR_MODBUS_ID, Main_Modbus_ID);
}
}
extern uint16_t Pm_1_0_value, Pm_2_5_value, Pm_10_value;
extern uint16_t CO2_Value;
uint8_t CO2_quality = 0;
uint8_t PM2_5_quality = 0;
uint8_t PM10_quality = 0;
uint8_t temp_fan_speed = 0;
uint8_t temp_pm_quality = 0;
#define CO2_HISTERISE 0
#define DUST_HISTERISE 0
void Air_Quality_process(void)
{
if(Power_On == 1)
{
if(CO2_Value <= 500-CO2_HISTERISE) CO2_quality = 0;
else if((CO2_Value > 500+CO2_HISTERISE)&&(CO2_Value <= 1000-CO2_HISTERISE)) CO2_quality = 0x01;
else if((CO2_Value > 1000+CO2_HISTERISE)&&(CO2_Value <= 1500-CO2_HISTERISE)) CO2_quality = 0x02;
else if(CO2_Value > 1500+CO2_HISTERISE)CO2_quality = 0x04;
//2020.5.26 PM2.5 기준변경
if(Pm_2_5_value <= 15-DUST_HISTERISE) PM2_5_quality = 0;
else if((Pm_2_5_value > 15+DUST_HISTERISE)&&(Pm_2_5_value <= 35-DUST_HISTERISE)) PM2_5_quality = 0x01;
else if((Pm_2_5_value > 35+DUST_HISTERISE)&&(Pm_2_5_value <= 75-DUST_HISTERISE)) PM2_5_quality = 0x02;
else if(Pm_2_5_value > 75+DUST_HISTERISE)PM2_5_quality = 0x04;
if(Pm_10_value <= 30-DUST_HISTERISE) PM10_quality = 0;
else if((Pm_10_value > 30+DUST_HISTERISE)&&(Pm_10_value <= 80-DUST_HISTERISE)) PM10_quality = 0x01;
else if((Pm_10_value > 80+DUST_HISTERISE)&&(Pm_10_value <= 150-DUST_HISTERISE)) PM10_quality = 0x02;
else if(Pm_10_value > 150+DUST_HISTERISE)PM10_quality = 0x04;
temp_pm_quality = PM2_5_quality | PM10_quality;
if(Tx_Run_Mode == MODE_AUTO)
{
if(CO2_quality == 0)
{
if(temp_pm_quality < 1)temp_fan_speed = 0;
else if(temp_pm_quality < 2)temp_fan_speed = 2;
else if(temp_pm_quality < 4)temp_fan_speed = 3;
else temp_fan_speed = 4;
}
else
{
if(CO2_quality == 0x01)
{
if(temp_pm_quality < 2)temp_fan_speed = 2;
else if(temp_pm_quality < 4)temp_fan_speed = 3;
else temp_fan_speed = 4;
}
else if(CO2_quality == 0x02)
{
if(temp_pm_quality < 4)temp_fan_speed = 3;
else temp_fan_speed = 4;
}
else if(CO2_quality == 0x04)
{
temp_fan_speed = 4;
}
}
Tx_Fan_Speed = temp_fan_speed;
}
}
}
extern uint8_t Blinking_Count, Blink_Toggle;
extern volatile uint8_t Filter_Reset_Flag;
extern volatile uint8_t Tx_Mode_Event , Tx_Fan_Event , Tx_Reserve_Event ;
volatile uint16_t Fan_Setting_Timer = 0;
void IR_Remocon_process(void)
{
switch(IR_Event_Code)
{
case IR_EVENT_POWER:
if(Power_On == 0)power_on_process();
else power_off_process();
break;
case IR_EVENT_WIND_UP:
if(Power_On == 1)
{
if((Tx_Run_Mode == MODE_AUTO)||(Tx_Run_Mode == MODE_BYPASS))
{
Melody_Mode = MELODY_NG;
}
else
{
if(Tx_Fan_Speed<5)Tx_Fan_Speed++;
Tx_Fan_Event = TX_EVENT;
Melody_Mode = MELODY_TOUCH;
}
}
break;
case IR_EVENT_WIND_DN:
if(Power_On == 1)
{
if((Tx_Run_Mode == MODE_AUTO)||(Tx_Run_Mode == MODE_BYPASS))
{
Melody_Mode = MELODY_NG;
}
else
{
if(Tx_Fan_Speed > 1)Tx_Fan_Speed--;
Tx_Fan_Event = TX_EVENT;
Melody_Mode = MELODY_TOUCH;
}
}
break;
case IR_EVENT_TIME_1:
if(Power_On == 1)
{
if(Tx_Reservation_Hour == 1)Tx_Reservation_Hour = 0;
else Tx_Reservation_Hour = 1;
if(Blinking_Count == 0)
{
Blink_Timer = 0;
Blink_Toggle = 0;
}
Blinking_Count = 3;
Melody_Mode = MELODY_TOUCH;
Tx_Reserve_Event = TX_EVENT;
}
break;
case IR_EVENT_TIME_2:
if(Power_On == 1)
{
if(Tx_Reservation_Hour == 4)Tx_Reservation_Hour = 0;
else Tx_Reservation_Hour = 4;
if(Blinking_Count == 0)
{
Blink_Timer = 0;
Blink_Toggle = 0;
}
Blinking_Count = 3;
Melody_Mode = MELODY_TOUCH;
Tx_Reserve_Event = TX_EVENT;
}
break;
case IR_EVENT_TIME_3:
if(Power_On == 1)
{
if(Tx_Reservation_Hour == 8)Tx_Reservation_Hour = 0;
else Tx_Reservation_Hour = 8;
if(Blinking_Count == 0)
{
Blink_Timer = 0;
Blink_Toggle = 0;
}
Blinking_Count = 3;
Melody_Mode = MELODY_TOUCH;
Tx_Reserve_Event = TX_EVENT;
}
break;
case IR_EVENT_MODE:
if(Power_On == 1)
{
if(Tx_Run_Mode == MODE_VENT)Tx_Run_Mode = MODE_AUTO;
else if(Tx_Run_Mode == MODE_AUTO)Tx_Run_Mode = MODE_VENT;
Tx_Reservation_Hour = 0;
Tx_Fan_Speed = 3;
Tx_Mode_Event = TX_EVENT;
Tx_Fan_Event = TX_EVENT;
Tx_Reserve_Event = TX_EVENT;
Melody_Mode = MELODY_TOUCH;
}
break;
case IR_EVENT_FILTER_RESET:
Filter_Reset_Flag = 1;
Melody_Mode = MELODY_TOUCH;
break;
default:
break;
}
if(IR_Event_Code)IR_Event_Code = 0;
}
@@ -0,0 +1,154 @@
/**************************************************************************//**
* @file main.c
* @version V1.00
* $Revision: 4 $
* $Date: 14/09/11 5:23p $
* @brief Show how to pixel on and off on LCD panel.
*
* @note
* Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "Nano100Series.h"
#include "adc.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "uart.h"
#include "sys.h"
#include "clk.h"
#include "EEPROM_Emulate.h"
#include "My_define.h"
#define __wdt_setting() SYS_UnlockReg(); WDT_Open(WDT_TIMEOUT_2POW14, 0, TRUE, FALSE); SYS_LockReg();
#define __wdt_reset() SYS_UnlockReg(); WDT_RESET_COUNTER(); SYS_LockReg();
extern volatile uint8_t Run_Timer;
extern volatile uint16_t mSec_Timer;
extern volatile uint16_t Blink_Timer;
extern volatile uint8_t Tx_Reservation_Hour, Rx_Reservation_Hour;
extern volatile uint8_t Reservation_Min;
extern volatile uint8_t Rx_Main_complete;
extern volatile uint8_t Tx_Data_Mode;
extern volatile uint8_t Tx_Main_Event_Flag;
extern uint16_t Main_Err_Code;
uint8_t Sec_Timer = 0;
uint8_t Blink_Toggle = 0;
uint8_t Blinking_Count = 0;
uint8_t In_Com_Error_Count = 0;
uint8_t Out_Com_Error_Count = 0;
uint8_t Sensor_Error_Count = 0;
extern volatile uint8_t IR_Event_Flag;
extern volatile uint8_t Rx_wifi_complete;
extern volatile uint16_t FastBlink_Timer;
uint8_t FastBlink_Toggle;
uint32_t Reset_src_value = 0;
void main(void)
{
__disable_interrupt();
SYS_Init();
SYS_EnableBOD(SYS_BODCTL_BOD25_RST_EN_Msk, SYS_BODCTL_BOD25_EN_Msk);
// ADC_Init();
GPIO_Init();
PWM_Init();
Timer0_Init();
Timer1_Init();
Timer2_Init();
// UART0_Init(); //
UART1_Init(); // to rs485 - internal
SC0_Init(); // to external
//SC1_Init(); // to wifi
Init_EEPROM(eep_data_size, eep_page_amount);
Search_Valid_Page();
__enable_interrupt();
Reset_src_value = SYS_GetResetSrc();
if((Reset_src_value & 0x00000037) != 0x00000004) // WDT reset
{
Processor_Init();
}
SYS_ClearResetSrc(Reset_src_value);
__wdt_setting();
Tx_Data_Mode = TX_DATA_MODE_REQUEST1;
while(1)
{
Touch_process();
com_rs485_process();
if(IR_Event_Flag == 1)
{
IR_Event_Flag = 0;
IR_Remocon_process();
}
if(Run_Timer == 0)
{
Run_Timer = 25;
Display_update();
Display_process();
}
if(mSec_Timer == 0)
{
mSec_Timer = 999;
if(In_Com_Error_Count++ >= 10){In_Com_Error_Count = 10;Main_Err_Code |= ERROR_IN_COM;}
if(Sensor_Error_Count++ >= 10){Sensor_Error_Count = 10;Main_Err_Code |= ERROR_CO2|ERROR_DUST;}
Air_Quality_process();
}
if(FastBlink_Timer == 0)
{
FastBlink_Timer = 249;
FastBlink_Toggle ^= 1;
}
if(Blink_Timer == 0)
{
Blink_Timer = 499;
if(Blink_Toggle == 0)
{
Blink_Toggle = 1;
}
else
{
Blink_Toggle = 0;
if(Blinking_Count)
{
Blinking_Count--;
}
}
__wdt_reset();
}
}
}
@@ -0,0 +1,986 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include "Nano100Series.h"
#include "adc.h"
#include "gpio.h"
#include "pwm.h"
#include "timer.h"
#include "uart.h"
#include "sys.h"
#include "clk.h"
#include "EEPROM_Emulate.h"
#include "My_define.h"
void Initial_Signal();
void Disp_Segdata(uint8_t Sel, uint8_t digit4, uint8_t digit3, uint8_t digit2, uint8_t digit1);
void Led_OnOff(uint8_t kind, uint8_t onoff);
uint8_t Font_Data[18]={0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x67,\
0x80, 0x58, 0x79, 0x40, 0x00, 0x50, 0x77, 0x5E };
// . , c , E , - , ' ' , r , A , d
uint8_t seg_data[4][14];
#define A_DATA PA4
#define A_CLK PA3
#define A_STB PA2
#define B_DATA PA13
#define B_CLK PA14
#define B_STB PA15
#define C_DATA PC9
#define C_CLK PC10
#define C_STB PC11
#define D_DATA PD15
#define D_CLK PD14
#define D_STB PD7
void Initial_Signal()
{
uint8_t i;
A_CLK = 1;B_CLK = 1;C_CLK = 1;D_CLK = 1;
A_STB = 1;B_STB = 1;C_STB = 1;D_STB = 1;
for(i=0; i<8; i++) //command 1 (#0000_0001B) -> 5grid 8seg
{
A_STB = 0;B_STB = 0;C_STB = 0;D_STB = 0;
A_CLK = 0;B_CLK = 0;C_CLK = 0;D_CLK = 0;
if(i==0)
{
A_DATA = 1;B_DATA = 1;C_DATA = 1;D_DATA = 1;
}
else
{
A_DATA = 0;B_DATA = 0;C_DATA = 0;D_DATA = 0;
}
A_CLK = 1;B_CLK = 1;C_CLK = 1;D_CLK = 1;
}
A_STB = 1;B_STB = 1;C_STB = 1;D_STB = 1;
for(i=0; i<8; i++) //command 2 (#0100_0000B)
{
A_STB = 0;B_STB = 0;C_STB = 0;D_STB = 0;
A_CLK = 0;B_CLK = 0;C_CLK = 0;D_CLK = 0;
if(i==6)
{
A_DATA = 1;B_DATA = 1;C_DATA = 1;D_DATA = 1;
}
else
{
A_DATA = 0;B_DATA = 0;C_DATA = 0;D_DATA = 0;
}
A_CLK = 1;B_CLK = 1;C_CLK = 1;D_CLK = 1;
}
A_STB = 1;B_STB = 1;C_STB = 1;D_STB = 1;
for(i=0; i<8; i++) //command 3 (#1100_0000B)
{
A_STB = 0;B_STB = 0;C_STB = 0;D_STB = 0;
A_CLK = 0;B_CLK = 0;C_CLK = 0;D_CLK = 0;
if(i==6 || i==7)
{
A_DATA = 1;B_DATA = 1;C_DATA = 1;D_DATA = 1;
}
else
{
A_DATA = 0;B_DATA = 0;C_DATA = 0;D_DATA = 0;
}
A_CLK = 1;B_CLK = 1;C_CLK = 1;D_CLK = 1;
}
// A_STB = 1;B_STB = 1;C_STB = 1;D_STB = 1;
for(i=0; i<112; i++) //data
{
A_STB = 0;B_STB = 0;C_STB = 0;D_STB = 0;
A_CLK = 0;B_CLK = 0;C_CLK = 0;D_CLK = 0;
A_DATA = 0;B_DATA = 0;C_DATA = 0;D_DATA = 0;
A_CLK = 1;B_CLK = 1;C_CLK = 1;D_CLK = 1;
}
A_STB = 1;B_STB = 1;C_STB = 1;D_STB = 1;
for(i=0; i<8; i++) //command 4 (#1000_0100B)
{
A_STB = 0;B_STB = 0;C_STB = 0;D_STB = 0;
A_CLK = 0;B_CLK = 0;C_CLK = 0;D_CLK = 0;
if(i==3 || i==7)
{
A_DATA = 1;B_DATA = 1;C_DATA = 1;D_DATA = 1;
}
else
{
A_DATA = 0;B_DATA = 0;C_DATA = 0;D_DATA = 0;
}
A_CLK = 1;B_CLK = 1;C_CLK = 1;D_CLK = 1;
}
A_STB = 1;B_STB = 1;C_STB = 1;D_STB = 1;
}
uint16_t one_sec = 0;
extern uint8_t Tmperature_Error;
void Disp_Segdata(uint8_t Sel, uint8_t digit4, uint8_t digit3, uint8_t digit2, uint8_t digit1)
{
seg_data[Sel][0] = Font_Data[digit4];
seg_data[Sel][1] = Font_Data[digit4]>>3;
seg_data[Sel][2] = Font_Data[digit3];
seg_data[Sel][3] = Font_Data[digit3]>>3;
seg_data[Sel][4] = Font_Data[digit2];
seg_data[Sel][5] = Font_Data[digit2]>>3;
seg_data[Sel][6] = Font_Data[digit1];
seg_data[Sel][7] = Font_Data[digit1]>>3;
}
enum{
K_VENT,
K_AUTO,
K_AIR,
K_WIND1,
K_WIND2,
K_WIND3,
K_WIND4,
K_WIND5,
K_PM25_1,
K_PM25_2,
K_PM25_4,
K_PM25_3,
K_PM10_1,
K_PM10_2,
K_PM10_4,
K_PM10_3,
K_TIME_1,
K_TIME_4,
K_TIME_8,
K_LOCK,
K_JUMKEOM,
K_FILTER_CLEAN,
K_FILTER_CHANGE,
K_EXTRA1,
K_CO2_1,
K_CO2_2,
K_CO2_4,
K_CO2_3,
K_SOJA_CLEAN,
K_SOJA_CHANGE,
K_IOT,
K_EXTRA2,
};
void Led_OnOff(uint8_t kind, uint8_t onoff)
{
if(onoff == 1)
{
if(kind < 6)
{
seg_data[3][0] |= 0x01<<kind;
}
else if(kind < 8)
{
seg_data[3][1] |= 0x01<<(kind-3);
}
else if(kind < 14)
{
seg_data[3][2] |= 0x01<<(kind-8);
}
else if(kind < 16)
{
seg_data[3][3] |=0x01<<(kind-8-3);
}
else if(kind < 22)
{
seg_data[3][4] |= 0x01<<(kind-16);
}
else if(kind < 24)
{
seg_data[3][5] |=0x01<<(kind-16-3);
}
else if(kind < 30)
{
seg_data[3][6] |= 0x01<<(kind-24);
}
else if(kind < 32)
{
seg_data[3][7] |=0x01<<(kind-24-3);
}
else // all on
{
seg_data[3][0] = 0xFF;
seg_data[3][1] = 0xFF;
seg_data[3][2] = 0xFF;
seg_data[3][3] = 0xFF;
seg_data[3][4] = 0xFF;
seg_data[3][5] = 0xFF;
seg_data[3][6] = 0xFF;
seg_data[3][7] = 0xFF;
}
}
else
{
if(kind < 6)
{
seg_data[3][0] &= ~(0x01<<kind);
}
else if(kind < 8)
{
seg_data[3][1] &= ~(0x01<<(kind-3));
}
else if(kind < 14)
{
seg_data[3][2] &= ~(0x01<<(kind-8));
}
else if(kind < 16)
{
seg_data[3][3] &= ~(0x01<<(kind-8-3));
}
else if(kind < 22)
{
seg_data[3][4] &= ~(0x01<<kind-16);
}
else if(kind < 24)
{
seg_data[3][5] &= ~(0x01<<(kind-16-3));
}
else if(kind < 30)
{
seg_data[3][6] &= ~(0x01<<kind-24);
}
else if(kind < 32)
{
seg_data[3][7] &= ~(0x01<<(kind-24-3));
}
else // all off
{
seg_data[3][0] = 0;
seg_data[3][1] = 0;
seg_data[3][2] = 0;
seg_data[3][3] = 0;
seg_data[3][4] = 0;
seg_data[3][5] = 0;
seg_data[3][6] = 0;
seg_data[3][7] = 0;
} }
}
void Make_A(void)
{
uint8_t i,j;
uint8_t Mask;
A_STB = 1;
A_CLK = 1;
for(i=0; i<8; i++) //command 1 (#0000_0011B)
{
A_STB = 0;
A_CLK = 0;
if( i==0) //5grid, 8segment
A_DATA = 1;
else
A_DATA = 0;
A_CLK = 1;
}
A_STB = 1;
for(i=0; i<8; i++) //command 2 (#0100_0000B)
{
A_STB = 0;
A_CLK = 0;
if(i==6) //command2:01
A_DATA = 1;
else
A_DATA = 0;
A_CLK = 1;
}
A_STB = 1;
for(i=0; i<8; i++) //command 3 (#1100_0000B)
{
A_STB = 0;
A_CLK = 0;
if(i==6 || i==7)
A_DATA = 1;
else
A_DATA = 0;
A_CLK = 1;
}
for(i=0; i<14; i++)
{
Mask = 0x01;
for(j=0; j<8; j++)
{
A_STB = 0;
A_CLK = 0;
if(seg_data[0][i] & Mask)A_DATA = 1;
else A_DATA = 0;
A_CLK = 1;
Mask <<= 1;
}
}
A_STB = 1;
for(i=0; i<8; i++) //command 4 (#1000_0100B)
{
A_STB = 0;
A_CLK = 0;
if(i==0 ||i==1 ||i==2 ||i==3 || i==7) //pulse width=14/16
A_DATA = 1;
else
A_DATA = 0;
A_CLK = 1;
}
A_STB = 1;
}
void Make_B(void)
{
uint8_t i,j;
uint8_t Mask;
B_STB = 1;
B_CLK = 1;
for(i=0; i<8; i++) //command 1 (#0000_0011B)
{
B_STB = 0;
B_CLK = 0;
if( i==0) //5grid, 8segment
B_DATA = 1;
else
B_DATA = 0;
B_CLK = 1;
}
B_STB = 1;
for(i=0; i<8; i++) //command 2 (#0100_0000B)
{
B_STB = 0;
B_CLK = 0;
if(i==6) //command2:01
B_DATA = 1;
else
B_DATA = 0;
B_CLK = 1;
}
B_STB = 1;
for(i=0; i<8; i++) //command 3 (#1100_0000B)
{
B_STB = 0;
B_CLK = 0;
if(i==6 || i==7)
B_DATA = 1;
else
B_DATA = 0;
B_CLK = 1;
}
for(i=0; i<14; i++)
{
Mask = 0x01;
for(j=0; j<8; j++)
{
B_STB = 0;
B_CLK = 0;
if(seg_data[1][i] & Mask)B_DATA = 1;
else B_DATA = 0;
B_CLK = 1;
Mask <<= 1;
}
}
B_STB = 1;
for(i=0; i<8; i++) //command 4 (#1000_0100B)
{
B_STB = 0;
B_CLK = 0;
if(i==0 ||i==1 ||i==2 ||i==3 || i==7) //pulse width=14/16
B_DATA = 1;
else
B_DATA = 0;
B_CLK = 1;
}
B_STB = 1;
}
void Make_C(void)
{
uint8_t i,j;
uint8_t Mask;
C_STB = 1;
C_CLK = 1;
for(i=0; i<8; i++) //command 1 (#0000_0011B)
{
C_STB = 0;
C_CLK = 0;
if( i==0) //5grid, 8segment
C_DATA = 1;
else
C_DATA = 0;
C_CLK = 1;
}
C_STB = 1;
for(i=0; i<8; i++) //command 2 (#0100_0000B)
{
C_STB = 0;
C_CLK = 0;
if(i==6) //command2:01
C_DATA = 1;
else
C_DATA = 0;
C_CLK = 1;
}
C_STB = 1;
for(i=0; i<8; i++) //command 3 (#1100_0000B)
{
C_STB = 0;
C_CLK = 0;
if(i==6 || i==7)
C_DATA = 1;
else
C_DATA = 0;
C_CLK = 1;
}
for(i=0; i<14; i++)
{
Mask = 0x01;
for(j=0; j<8; j++)
{
C_STB = 0;
C_CLK = 0;
if(seg_data[2][i] & Mask)C_DATA = 1;
else C_DATA = 0;
C_CLK = 1;
Mask <<= 1;
}
}
C_STB = 1;
for(i=0; i<8; i++) //command 4 (#1000_0100B)
{
C_STB = 0;
C_CLK = 0;
if(i==0 ||i==1 ||i==2 ||i==3 || i==7) //pulse width=14/16
C_DATA = 1;
else
C_DATA = 0;
C_CLK = 1;
}
C_STB = 1;
}
void Make_D(void)
{
uint8_t i,j;
uint8_t Mask;
D_STB = 1;
D_CLK = 1;
for(i=0; i<8; i++) //command 1 (#0000_0011B)
{
D_STB = 0;
D_CLK = 0;
if( i==0) //5grid, 8segment
D_DATA = 1;
else
D_DATA = 0;
D_CLK = 1;
}
D_STB = 1;
for(i=0; i<8; i++) //command 2 (#0100_0000B)
{
D_STB = 0;
D_CLK = 0;
if(i==6) //command2:01
D_DATA = 1;
else
D_DATA = 0;
D_CLK = 1;
}
D_STB = 1;
for(i=0; i<8; i++) //command 3 (#1100_0000B)
{
D_STB = 0;
D_CLK = 0;
if(i==6 || i==7)
D_DATA = 1;
else
D_DATA = 0;
D_CLK = 1;
}
for(i=0; i<14; i++)
{
Mask = 0x01;
for(j=0; j<8; j++)
{
D_STB = 0;
D_CLK = 0;
if(seg_data[3][i] & Mask)D_DATA = 1;
else D_DATA = 0;
D_CLK = 1;
Mask <<= 1;
}
}
D_STB = 1;
for(i=0; i<8; i++) //command 4 (#1000_0100B)
{
D_STB = 0;
D_CLK = 0;
if(i==0 ||i==1 ||i==2 ||i==3 || i==7) //pulse width=14/16
D_DATA = 1;
else
D_DATA = 0;
D_CLK = 1;
}
D_STB = 1;
}
extern volatile uint8_t Power_On;
extern volatile uint8_t Tx_Run_Mode;
extern volatile uint8_t Tx_Fan_Speed;
extern volatile uint8_t Tx_Reservation_Hour;
extern uint16_t Pm_1_0_value, Pm_2_5_value, Pm_10_value;
extern uint16_t CO2_Value;
extern uint8_t CO2_quality;
extern uint8_t PM2_5_quality;
extern uint8_t PM10_quality;
extern uint8_t Kids_Lock;
extern uint16_t Main_Err_Code;
extern uint8_t Vsp_Mode;
extern uint8_t Test_Mode_Step;
extern uint8_t Test_Mode_Sa_Ea_Sel;
extern uint8_t Main_Modbus_ID;
extern uint8_t Ventilation_SA[5];
extern uint8_t Ventilation_EA[5];
extern uint8_t AirClean_SA[5];
extern uint8_t AirClean_EA[5];
extern uint8_t Bypass_SA[5];
extern uint8_t Bypass_EA[5];
extern uint16_t SA_rpm, EA_rpm;
extern uint8_t Wifi_Status;
extern uint8_t Blink_Toggle, FastBlink_Toggle;
void Display_update(void)
{
uint8_t Num_1000, Num_100, Num_10, Num_1;
uint8_t Tmp_Speed = 0;
uint16_t Err;
if(Vsp_Mode == TX_DATA_MODE_SETTING)
{
Led_OnOff(100, 0); // all off
Disp_Segdata(2, 14, 14, 14, 14); // ALL OFF
if((Test_Mode_Step >= 1)&&(Test_Mode_Step <= 5)) // vent
{
Led_OnOff(K_VENT, 1);
Tmp_Speed = Test_Mode_Step-1;
if(Test_Mode_Sa_Ea_Sel == 0)
{
Disp_Segdata(0, 14, 5, 16, 14); // " SA "
Num_10 = Ventilation_SA[Tmp_Speed]%100/10;
Num_1 = Ventilation_SA[Tmp_Speed]%10;
Disp_Segdata(1, 14, 14, Num_10, Num_1);
Num_1000 = (uint8_t)(SA_rpm%10000/1000);
Num_100 = (uint8_t)(SA_rpm%1000/100);
Num_10 = (uint8_t)(SA_rpm%100/10);
Num_1 = (uint8_t)(SA_rpm%10);
Disp_Segdata(2, Num_1000, Num_100, Num_10, Num_1);
}
else
{
Disp_Segdata(0, 14, 12, 16, 14); // " EA "
Num_10 = Ventilation_EA[Tmp_Speed]%100/10;
Num_1 = Ventilation_EA[Tmp_Speed]%10;
Disp_Segdata(1, 14, 14, Num_10, Num_1);
Num_1000 = (uint8_t)(EA_rpm%10000/1000);
Num_100 = (uint8_t)(EA_rpm%1000/100);
Num_10 = (uint8_t)(EA_rpm%100/10);
Num_1 = (uint8_t)(EA_rpm%10);
Disp_Segdata(2, Num_1000, Num_100, Num_10, Num_1);
}
}
else if((Test_Mode_Step >= 6)&&(Test_Mode_Step <= 10)) // air
{
Led_OnOff(K_AIR, 1);
Tmp_Speed = Test_Mode_Step-6;
if(Test_Mode_Sa_Ea_Sel == 0)
{
Disp_Segdata(0, 14, 5, 16, 14); // " SA "
Num_10 = AirClean_SA[Tmp_Speed]%100/10;
Num_1 = AirClean_SA[Tmp_Speed]%10;
Disp_Segdata(1, 14, 14, Num_10, Num_1);
Num_1000 = (uint8_t)(SA_rpm%10000/1000);
Num_100 = (uint8_t)(SA_rpm%1000/100);
Num_10 = (uint8_t)(SA_rpm%100/10);
Num_1 = (uint8_t)(SA_rpm%10);
Disp_Segdata(2, Num_1000, Num_100, Num_10, Num_1);
}
else
{
Disp_Segdata(0, 14, 12, 16, 14); // " EA "
Num_10 = AirClean_EA[Tmp_Speed]%100/10;
Num_1 = AirClean_EA[Tmp_Speed]%10;
Disp_Segdata(1, 14, 14, Num_10, Num_1);
Num_1000 = (uint8_t)(EA_rpm%10000/1000);
Num_100 = (uint8_t)(EA_rpm%1000/100);
Num_10 = (uint8_t)(EA_rpm%100/10);
Num_1 = (uint8_t)(EA_rpm%10);
Disp_Segdata(2, Num_1000, Num_100, Num_10, Num_1);
}
}
switch(Test_Mode_Step)
{
case 1:
case 6:
case 11:
Led_OnOff(K_WIND1, 1);
break;
case 2:
case 7:
case 12:
Led_OnOff(K_WIND2, 1);
break;
case 3:
case 8:
case 13:
Led_OnOff(K_WIND3, 1);
break;
case 4:
case 9:
case 14:
Led_OnOff(K_WIND4, 1);
break;
case 5:
case 10:
case 15:
Led_OnOff(K_WIND5, 1);
break;
case 16:
Disp_Segdata(0, 14, 1, 17, 14); // " Id "
Num_10 = Main_Modbus_ID%100/10;
Num_1 = Main_Modbus_ID%10;
Disp_Segdata(1, 14, 14, Num_10, Num_1);
break;
case 0x11:
if(Main_BxD_FW_Version[1] == 'J')Num_1000 = 18; //J
else if(Main_BxD_FW_Version[1] == 'I')Num_1000 = 1; //I
else Num_1000 = 13; //-
Num_10 = Main_BxD_FW_Version[2]/10;
Num_1 = Main_BxD_FW_Version[2]%10;
Disp_Segdata(0, Num_1000, 13, Num_10, Num_1); // " J- " 메인 버전
Num_10 = ROOMCON_FW_VERSION/10;
Num_1 = ROOMCON_FW_VERSION%10;
Disp_Segdata(1, 1, 13, Num_10, Num_1); // " I- " 룸콘 버전
Num_10 = Sensor_BxD_Version/10;
Num_1 = Sensor_BxD_Version%10;
Disp_Segdata(2, 5, 13, Num_10, Num_1); // " S- " 센서보드 버전
break;
default:
break;
}
return;
}
////////////////////////////////////////////////////////////////
Led_OnOff(100, 0); // all off
if(Wifi_Status == 1) // connect
{
Led_OnOff(K_IOT, 1);
}
else if(Wifi_Status == 2) // wait slow
{
Led_OnOff(K_IOT, Blink_Toggle);
}
else if(Wifi_Status == 3) // fast
{
Led_OnOff(K_IOT, FastBlink_Toggle);
}
else // dis connect
{
Led_OnOff(K_IOT, 0);
}
Err = Main_Err_Code&(ERROR_FILTER_CLEAN|ERROR_FILTER_CHANGE|ERROR_SOJA_CHANGE|ERROR_SA|ERROR_EA|ERROR_TEMP|ERROR_CO2|ERROR_DUST|ERROR_IN_COM);
if(Err)Led_OnOff(K_JUMKEOM, 1);
////////////////////////////////////////////////////////////////
if(Power_On == 0)
{
Disp_Segdata(0, 14, 14, 14, 14); // ALL OFF
Disp_Segdata(1, 14, 14, 14, 14); // ALL OFF
Disp_Segdata(2, 14, 14, 14, 14); // ALL OFF
if(Main_Err_Code)Led_OnOff(K_JUMKEOM, 1);
if(Main_Err_Code&ERROR_FILTER_CLEAN)
{
Led_OnOff(K_FILTER_CLEAN, 1);
Led_OnOff(K_SOJA_CLEAN, 1);
}
else if(Main_Err_Code&ERROR_FILTER_CHANGE)
{
Led_OnOff(K_FILTER_CHANGE, 1);
}
else if(Main_Err_Code&ERROR_SOJA_CHANGE)
{
Led_OnOff(K_SOJA_CHANGE, 1);
}
else if(Main_Err_Code&ERROR_SA)
{
Disp_Segdata(1, 12, 13, 0, 9); // E-09
}
else if(Main_Err_Code&ERROR_EA)
{
Disp_Segdata(1, 12, 13, 1, 0); // E-10
}
else if(Main_Err_Code&ERROR_TEMP)
{
Disp_Segdata(1, 12, 13, 0, 2); // E-02
}
else if(Main_Err_Code&ERROR_HUMI)
{
;
}
else if(Main_Err_Code&ERROR_TVOC)
{
;
}
else if(Main_Err_Code&ERROR_CO2)
{
Disp_Segdata(1, 12, 13, 0, 6); // E-06
}
else if(Main_Err_Code&ERROR_DUST)
{
Disp_Segdata(1, 12, 13, 1, 8); // E-08
}
else if(Main_Err_Code&ERROR_IN_COM)
{
Disp_Segdata(1, 12, 13, 0, 7); // E-07
}
return;
}
Num_1000= Num_100= Num_10= Num_1= 14; // blank
if(CO2_Value>=1000)Num_1000 = CO2_Value%10000/1000;
if(CO2_Value>=100)Num_100 = CO2_Value%1000/100;
if(CO2_Value>=10)Num_10 = CO2_Value%100/10;
Num_1 = CO2_Value%10;
Disp_Segdata(2, Num_1000, Num_100, Num_10, Num_1);
Num_1000= Num_100= Num_10= Num_1= 14; // blank
if(Pm_10_value>=1000)Num_1000 = Pm_10_value%10000/1000;
if(Pm_10_value>=100)Num_100 = Pm_10_value%1000/100;
if(Pm_10_value>=10)Num_10 = Pm_10_value%100/10;
Num_1 = Pm_10_value%10;
Disp_Segdata(1, Num_1000, Num_100, Num_10, Num_1);
Num_1000= Num_100= Num_10= Num_1= 14; // blank
if(Pm_2_5_value>=1000)Num_1000 = Pm_2_5_value%10000/1000;
if(Pm_2_5_value>=100)Num_100 = Pm_2_5_value%1000/100;
if(Pm_2_5_value>=10)Num_10 = Pm_2_5_value%100/10;
Num_1 = Pm_2_5_value%10;
Disp_Segdata(0, Num_1000, Num_100, Num_10, Num_1);
switch(CO2_quality)
{
case 0x00: Led_OnOff(K_CO2_1, 1);break;
case 0x01: Led_OnOff(K_CO2_2, 1);break;
case 0x02: Led_OnOff(K_CO2_3, 1);break;
case 0x04:
default:
Led_OnOff(K_CO2_3, 1);
Led_OnOff(K_CO2_4, 1);
break;
}
switch(PM2_5_quality)
{
case 0x00: Led_OnOff(K_PM25_1, 1);break;
case 0x01: Led_OnOff(K_PM25_2, 1); break;
case 0x02: Led_OnOff(K_PM25_3, 1); break;
case 0x04:
default:
Led_OnOff(K_PM25_3, 1);
Led_OnOff(K_PM25_4, 1);
break;
}
switch(PM10_quality)
{
case 0:
Led_OnOff(K_PM10_1, 1);
break;
case 0x01:
Led_OnOff(K_PM10_2, 1);
break;
case 0x02:
Led_OnOff(K_PM10_3, 1);
break;
case 0x04:
default:
Led_OnOff(K_PM10_3, 1);
Led_OnOff(K_PM10_4, 1);
break;
}
switch(Tx_Run_Mode)
{
case MODE_VENT: Led_OnOff(K_VENT, 1); break;
case MODE_AUTO: Led_OnOff(K_AUTO, 1);break;
case MODE_AIR_CLEAN: Led_OnOff(K_AIR, 1); break;
default: break;
}
switch(Tx_Fan_Speed)
{
case 1: Led_OnOff(K_WIND1, 1);break;
case 2: Led_OnOff(K_WIND2, 1);break;
case 3: Led_OnOff(K_WIND3, 1);break;
case 4: Led_OnOff(K_WIND4, 1);break;
case 5: Led_OnOff(K_WIND5, 1);break;
default: break;
}
switch(Tx_Reservation_Hour)
{
case 1:
case 2:
case 3:
Led_OnOff(K_TIME_1, 1);
break;
case 4:
case 5:
case 6:
case 7:
Led_OnOff(K_TIME_4, 1);
break;
case 8:
Led_OnOff(K_TIME_8, 1);
break;
default:
break;
}
Led_OnOff(K_LOCK, Kids_Lock);
}
uint8_t Sel_Pos = 0;
void Display_process(void)
{
switch(Sel_Pos)
{
case 0:
Make_A();
Sel_Pos++;
break;
case 1:
Make_B();
Sel_Pos++;
break;
case 2:
Make_C();
Sel_Pos++;
break;
case 3:
default:
Make_D();
Sel_Pos = 0;
break;
}
}

Some files were not shown because too many files have changed in this diff Show More