commit 901b58cd27b348f334fe3d9fdb65dbaff5550108 Author: doryan Date: Mon Apr 21 21:36:22 2025 +0400 first commit diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8e0a654 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "soft-serial" +version = "0.1.0" +edition = "2021" + +[dependencies.arduino-hal] +git = "https://github.com/rahix/avr-hal" +rev = "3e362624547462928a219c40f9ea8e3a64f21e5f" +features = ["sparkfun-promicro"] + +[dependencies.static_pins] +git = "https://gitea.doryan04.ru/TheEmbeddedRust/static_pins" + +[dependencies.avr-device] +version = "0.5.4" + +[profile.dev] +panic = "abort" +codegen-units = 1 +debug = true +lto = true +opt-level = "s" + +[profile.release] +panic = "abort" +lto = true +opt-level = "s" diff --git a/avr-specs/avr-atmega1280.json b/avr-specs/avr-atmega1280.json new file mode 100644 index 0000000..1791c43 --- /dev/null +++ b/avr-specs/avr-atmega1280.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega1280", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega1280", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega1280", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega1284p.json b/avr-specs/avr-atmega1284p.json new file mode 100644 index 0000000..38c9162 --- /dev/null +++ b/avr-specs/avr-atmega1284p.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega1284p", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega1284p", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega1284p", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega128a.json b/avr-specs/avr-atmega128a.json new file mode 100644 index 0000000..2707fab --- /dev/null +++ b/avr-specs/avr-atmega128a.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega128a", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega128a", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega128a", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega164pa.json b/avr-specs/avr-atmega164pa.json new file mode 100644 index 0000000..256a222 --- /dev/null +++ b/avr-specs/avr-atmega164pa.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega164pa", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega164pa", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega164pa", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega168.json b/avr-specs/avr-atmega168.json new file mode 100644 index 0000000..7fbd579 --- /dev/null +++ b/avr-specs/avr-atmega168.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega168", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega168", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega168", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega2560.json b/avr-specs/avr-atmega2560.json new file mode 100644 index 0000000..252b54f --- /dev/null +++ b/avr-specs/avr-atmega2560.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega2560", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega2560", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega2560", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega328.json b/avr-specs/avr-atmega328.json new file mode 100644 index 0000000..77c64f3 --- /dev/null +++ b/avr-specs/avr-atmega328.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega328", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega328", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega328", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega328p.json b/avr-specs/avr-atmega328p.json new file mode 100644 index 0000000..461daa7 --- /dev/null +++ b/avr-specs/avr-atmega328p.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega328p", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega328p", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega328p", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega32a.json b/avr-specs/avr-atmega32a.json new file mode 100644 index 0000000..9ffda7d --- /dev/null +++ b/avr-specs/avr-atmega32a.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega32a", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega32a", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega32a", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega32u4.json b/avr-specs/avr-atmega32u4.json new file mode 100644 index 0000000..a163214 --- /dev/null +++ b/avr-specs/avr-atmega32u4.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega32u4", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega32u4", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega32u4", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega48p.json b/avr-specs/avr-atmega48p.json new file mode 100644 index 0000000..508677e --- /dev/null +++ b/avr-specs/avr-atmega48p.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega48p", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega48p", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega48p", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-atmega8.json b/avr-specs/avr-atmega8.json new file mode 100644 index 0000000..b2c0c5c --- /dev/null +++ b/avr-specs/avr-atmega8.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "atmega8", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=atmega8", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=atmega8", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-attiny167.json b/avr-specs/avr-attiny167.json new file mode 100644 index 0000000..3cbdbe4 --- /dev/null +++ b/avr-specs/avr-attiny167.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "attiny167", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=attiny167", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=attiny167", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-attiny2313.json b/avr-specs/avr-attiny2313.json new file mode 100644 index 0000000..aa8fffb --- /dev/null +++ b/avr-specs/avr-attiny2313.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "attiny2313", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=attiny2313", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=attiny2313", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-attiny85.json b/avr-specs/avr-attiny85.json new file mode 100644 index 0000000..d5334aa --- /dev/null +++ b/avr-specs/avr-attiny85.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "attiny85", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=attiny85", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=attiny85", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/avr-specs/avr-attiny88.json b/avr-specs/avr-attiny88.json new file mode 100644 index 0000000..1af5e8d --- /dev/null +++ b/avr-specs/avr-attiny88.json @@ -0,0 +1,41 @@ +{ + "arch": "avr", + "atomic-cas": false, + "cpu": "attiny88", + "crt-objects-fallback": "false", + "data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8", + "eh-frame-header": false, + "exe-suffix": ".elf", + "late-link-args": { + "gnu-cc": [ + "-lgcc" + ], + "gnu-lld-cc": [ + "-lgcc" + ] + }, + "linker": "avr-gcc", + "linker-flavor": "gnu-cc", + "llvm-target": "avr-unknown-unknown", + "max-atomic-width": 8, + "metadata": { + "description": null, + "host_tools": null, + "std": null, + "tier": null + }, + "no-default-libraries": false, + "pre-link-args": { + "gnu-cc": [ + "-mmcu=attiny88", + "-Wl,--as-needed,--print-memory-usage" + ], + "gnu-lld-cc": [ + "-mmcu=attiny88", + "-Wl,--as-needed,--print-memory-usage" + ] + }, + "relocation-model": "static", + "target-c-int-width": "16", + "target-pointer-width": "16" +} diff --git a/rust-toolchain.toml b/rust-toolchain.toml new file mode 100644 index 0000000..7e59f6a --- /dev/null +++ b/rust-toolchain.toml @@ -0,0 +1,4 @@ +[toolchain] +channel = "nightly-2024-06-13" +components = [ "rust-src" ] +profile = "default" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..efe9e0d --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,207 @@ +use core::marker::PhantomData; + +use arduino_hal::{ + delay_us, + pac::EXINT, + port::{ + mode::{Input, PullUp}, + Pin, PinOps, + }, +}; + +use avr_device::asm::delay_cycles; + +use static_pins::StaticPinOps; + +pub type PollResult = Result<(), PollError>; +pub type ReadByteResult = Result; +pub type CorruptedData = (u8, u8); + +const SERIAL_DELAY: u32 = 4; +const FIRST_HALF_SERIAL_DELAY: u32 = SERIAL_DELAY / 2; +const SECOND_HALF_SERIAL_DELAY: u32 = SERIAL_DELAY - FIRST_HALF_SERIAL_DELAY; + +const READING_ADJUST: u32 = 16; +const FIRST_ENTRY_READING: u32 = 30; +const LSB: u8 = 0x01; +const MSB: u8 = 0x80; + +pub enum PollError { + NotFound, + NotReady, +} + +pub struct HalfDuplexSerial

{ + _pin: PhantomData, P>>, +} + +impl

HalfDuplexSerial

+where + P: PinOps + StaticPinOps, +{ + #[inline] + pub fn new(_pin: Pin, P>, exint: &EXINT) -> Self { + exint.eimsk.write(|w| w.bits(1 << 1)); + exint.eicra.write(|w| unsafe { w.bits(!(1 << 3 | 1 << 2)) }); + + Self { + _pin: PhantomData {}, + } + } +} + +pub trait SoftSerial

+where + P: PinOps + StaticPinOps, +{ + fn poll(&self) -> PollResult; + fn response(&self); + + fn sync_reciever(&self); + fn sync_transmitter(&self); + + fn write_byte(&self, data: u8); + fn read_byte(&self) -> ReadByteResult; + + #[inline] + fn finish_write(&self) { + P::into_pull_up_input(); + while P::is_low() {} + } + + fn write_bytes(&self, transmit_data: &[u8]) { + for byte in transmit_data { + self.write_byte(*byte); + self.sync_transmitter(); + } + } + + fn read_bytes(&self, recieve_buffer: &mut [u8]) { + for byte in recieve_buffer { + if let Ok(data) = self.read_byte() { + *byte = data; + } + self.sync_reciever(); + } + } +} + +impl

SoftSerial

for HalfDuplexSerial

+where + P: PinOps + StaticPinOps, +{ + fn poll(&self) -> PollResult { + P::into_output(); + delay_cycles(1); + P::into_pull_up_input(); + + delay_us(SERIAL_DELAY); + + if P::is_low() { + return PollResult::Err(PollError::NotFound); + } + + delay_us(SERIAL_DELAY); + + if P::is_high() { + return PollResult::Err(PollError::NotReady); + } + + while P::is_low() {} + + PollResult::Ok(()) + } + + fn response(&self) { + P::into_output_high(); + + delay_us(FIRST_HALF_SERIAL_DELAY); + + P::set_low(); + + delay_us(SERIAL_DELAY); + + P::into_pull_up_input(); + } + + #[inline(never)] + fn sync_transmitter(&self) { + P::into_output(); + + delay_us(SERIAL_DELAY); + + P::set_high(); + } + + #[inline(never)] + fn sync_reciever(&self) { + while P::is_high() {} + + while P::is_low() {} + } + + #[inline(never)] + fn write_byte(&self, data: u8) { + let (mut data, mut parity_bit) = (data, 0); + + for _ in 0..8 { + if data & MSB == 0 { + P::set_high(); + parity_bit ^= 0; + } else { + P::set_low(); + parity_bit ^= 1; + } + + delay_us(SERIAL_DELAY); + + data <<= 1; + } + + // Hamming code and CRC are very weightful and slow, so I use simple parity check + + if parity_bit == 0 { + P::set_high(); + } else { + P::set_low(); + } + + delay_us(SERIAL_DELAY); + } + + #[inline(never)] + fn read_byte(&self) -> ReadByteResult { + let (mut data, mut reciever_parity_bit) = (0, 0); + + delay_cycles(FIRST_ENTRY_READING); + for _ in 0..8 { + delay_us(FIRST_HALF_SERIAL_DELAY); + + if P::is_low() { + data |= 1; + reciever_parity_bit ^= 1; + } else { + data |= 0; + reciever_parity_bit ^= 0; + } + + delay_cycles(READING_ADJUST); + delay_us(SECOND_HALF_SERIAL_DELAY); + + data <<= 1; + } + + delay_us(FIRST_HALF_SERIAL_DELAY); + + let transmitter_parity_bit = (P::read() >> P::PIN_NUM) & LSB; + + delay_cycles(READING_ADJUST); + delay_us(SECOND_HALF_SERIAL_DELAY); + + if reciever_parity_bit != transmitter_parity_bit { + return Err((data, reciever_parity_bit)); + } + + Ok(data) + } +}