Expand description

Manchester Decoder

Features:

  • Decode monotonically sampled data stream that is Manchester modulated like it is used in Philips RC5

    https://techdocs.altium.com/display/FPGA/Philips+RC5+Infrared+Transmission+Protocol

  • High/low IN-Activitity configuration

  • Automatic start and end of datagram detection

  • Sampling needs to be 3 times the length of half a bit. (i.e. only a single periodic timer is needed), for a infrared receiver 889 µs halfbit period => the periodic timer should run all 297 µs.

Manchester Modulation

https://en.wikipedia.org/wiki/Manchester_code

  • A datagram starts after a pause period longer than the time of two bits
  • A datagram is finished if their is no edge anymore longer than a bit period and all subsequent samples are at inactive level
  • all other situations are treated as errors and are rejected
  • Bit order of a datagram:
    • The first bit received is the most significant bit (MSB) and the last bit

Receiving Algorithm Details

A Periodic sampling is used.

  • Three samples per half bit period, will do. It gives a one third (of half period) tolerance. And allows for one third (of half period) where the signal is expected to be stable.

    Thus, the Philips half bit time can vary 889 µs +/- 296 µs = [595; 1175] µs

  • For every bit there is an edge at the transition from first half bit to second half bit. This is period is used to synchronize bit value measurement

  • The first bit value must be pre-known, because it determines where the synchronization edges are to be expected:

    |

Example

The lib runs in no_std environments

#![deny(warnings)]
#![deny(unsafe_code)]
#![no_main]
#![no_std]

use nucleo_stm32g071rb as board; //  it also includes mem, defmt

use board::hal::prelude::*;
use board::hal::stm32;
use board::hal::nb::block;

use manchester_code::{ActivityLevel, SyncOnTurningEdge, BitOrder, Decoder};

#[cortex_m_rt::entry]
fn main() -> ! {
    let dp = stm32::Peripherals::take().expect("cannot take peripherals");
    let mut rcc = dp.RCC.constrain();

    let gpioa = dp.GPIOA.split(&mut rcc);
    let infrared = gpioa.pa8.into_pull_up_input();

    let mut timer = dp.TIM17.timer(&mut rcc);
    timer.start(297.us());
        let mut receiver = Decoder::new(
            ActivityLevel::High,
            SyncOnTurningEdge::First,
            BitOrder::LittleEndian);
    loop {
        match receiver.next(infrared.is_high().unwrap()) {
            None => (),
            Some(t) => if t.length() > 2 {
                defmt::println!("Datagram: {:?}",  t ); },
        };
        block!(timer.wait()).unwrap();
    }
}

Structs

Representation of a datagram

Decode a Manchester encoded stream of periodically taken samples into a datagram.

Encodes a datagram to Manchester code

Control sending of datagrams, manage infrared radiation pollution

Enums

Activity level of the Pin where the infrared receiver is attached to. It is the opposite level the pin takes if no datagram is transmitted.

BitOrder or endian describes the ordering of bits during transmission

A priori knowledge about the first expected bit of a telegram