m17

package module
v0.2.23 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 5, 2026 License: Apache-2.0 Imports: 26 Imported by: 0

README

M17 library, gateway and clients, written in Go

M17 Packet Mode is defined in the spec, and messaging is one obvious application. This project started as a set of tools to jumpstart messaging and data communications using the M17 ham radio mode. It has evolved to provide more general tool and library support for M17.

There are several tools and a library here:

Tools

M17 Gateway

m17-gateway bridges between RF clients and relays/reflectors. It currently supports the CC1200 Pi HAT. When run on a Raspberry Pi with a CC1200 HAT, it can forward M17 voice and packet traffic to and from a reflector/relay, making the Pi/CC1200 HAT an M17 voice and packet hotspot.

The easiest way to get a working CC1200 hotspot, including m17-gateway and a web dashboard is using DK1MI's excellent installer script. Highly recommended!

Another way to install just the gateway is using the APT package from a release on Github. To install it:

  1. Copy the URL for the latest deb package from https://github.com/jancona/m17/releases
  2. From a shell on the Pi do:
wget <latetst deb URL>
sudo dpkg -i m17-gateway_<version>_arm64.deb

To build it just run go build in the m17-gateway directory. Because Go natively supports cross-compilation, you can build a Raspberry Pi executable on any machine by running GOOS=linux GOARCH=arm64 go build, the using scp to copy the resulting executable to the Pi.

Usage of gateway:
  -config string
    	Configuration file (default "./gateway.ini")
  -h	Print arguments
  -in string
    	M17 symbol input (default stdin)
  -out string
    	M17 symbol output (default stdout)
Configuration

Bu default, the gateway looks for configuration in gateway.ini in the working directory. See m17-gateway/gateway.ini.sample for details.

GUI Messaging Client

m17-message is a cross-platform GUI network messaging client. It's based on Fybro, a messaging app built using Fyne, a fraemwork for building multi-platform GUI apps in Go. To build the client just run go build in the m17-message directory. For more packaging options, see the Fyne docs.

CLI Messaging Client

m17-text-cli is a rudimentary network messaging client--think Droidstar but for text messages (and not nearly as nice looking). Note that since I started writing this a number of tools (including DroidStar) have added M17 messaging support.

To build the client just run go build in the m17-text-cli directory.

Example: ./m17-text-cli -server relay.kc1awv.net -callsign N1ADJ

The program will respond with a prompt > . To send a message, enter callsign: message. Incoming messages for you will appear starting with < . To quit, enter /quit.

Sample session:

$ ./m17-text-cli -server relay.kc1awv.net
> N1ADJ: Hi from my other window!
>
2025-02-06 14:45:45 N0CALL>@ALL: Hi back
> /quit

Command line arguments:

Usage of ./m17-text-cli:
  -callsign string
    	User's callsign (default "N0CALL")
  -h	Print arguments
  -module string
      Module to connect to (default "P")
  -port uint
    	Port the reflector listens on (default 17000)
  -server string
    	Reflector server
CC1200 Modem Emulator

This program emulates the CC1200 Modem firmware. It accepts samples from the gateway and echos them back. It was used for development of the gateway until I had a real CC1200 hat to test with.

Library

The root directory of the project contains the Go library (github.com/jancona/m17) used to implement the M17 protocol parts of the tools. It's pretty rough right now, but I hope to improve it and make it more general and useful over time.

Documentation

Index

Constants

View Source
const (
	SymbolsPerSyncword = 8   //symbols per syncword
	SymbolsPerPayload  = 184 //symbols per payload in a frame
	SymbolsPerFrame    = 192 //symbols per whole 40 ms frame, 40ms * 4800 = 192
	BytesPerFrame      = SymbolsPerFrame * BitsPerSymbol / 8
	BitsPerSymbol      = 2
	BitsPerPayload     = SymbolsPerPayload * BitsPerSymbol
	FrameTime          = 40 * time.Millisecond
	FramesPerSecond    = time.Second / FrameTime
)
View Source
const (
	PacketModeFinalBit = 5 // use 6 bits of final byte
	LSFFinalBit        = 7 // use entire final byte
)
View Source
const (
	ConvolutionK      = 5                         //constraint length K=5
	ConvolutionStates = (1 << (ConvolutionK - 1)) //number of states of the convolutional encoder
)
View Source
const (
	LSFSync    = uint16(0x55F7)
	StreamSync = uint16(0xFF5D)
	PacketSync = uint16(0x75FF)
	BERTSync   = uint16(0xDF55)
	EOTMarker  = uint16(0x555D)
)
View Source
const (
	EncodedCallsignLen    = 6
	MaxCallsignLen        = 9
	DestinationAll        = "@ALL"
	EncodedDestinationAll = 0xFFFFFFFFFFFF
	MaxEncodedCallsign    = 0xEE6B27FFFFFF
	SpecialEncodedRange   = 268697600000000 //40^9+40^8
)
View Source
const (
	// SoftZero represents a confident 0 bit
	SoftZero = 0x0000
	// SoftOne represents a confident 1 bit
	SoftOne = 0xFFFF
	// SoftErasure represents an uncertain/erased bit
	SoftErasure = 0x7FFF
	// SoftThreshold is the decision boundary
	SoftThreshold = 0x7FFF
)

Constants for soft-decision logic

View Source
const (
	LSFLen = 30
	LSDLen = 28
)
View Source
const (
	RXSymbolScalingCoeff = (1.0 / (0.8 / (40.0e3 / 2097152 * 0xAD) * 130.0))

	TXSymbolScalingCoeff = (0.8 / ((40.0e3 / 2097152) * 0xAD) * 64.0)
)
View Source
const CRCLen = 2
View Source
const ErrorDetectionFailed = 0xFFFFFFFF

ErrorDetectionFailed indicates the decoder could not correct the errors

Variables

View Source
var (
	// TX symbols
	SymbolMap = []Symbol{+1, +3, -1, -3}

	// symbol list (RX)
	SymbolList = []Symbol{-3, -1, +1, +3}

	// End of Transmission symbol pattern
	EOTSymbols = []Symbol{+3, +3, +3, +3, +3, +3, -3, +3}
)
View Source
var (
	LSFPreambleSymbols = []float64{+3, -3, +3, -3, +3, -3, +3, -3}

	LSFSyncSymbols    = []float64{+3, +3, +3, +3, -3, -3, +3, -3} // 0x55F7
	ExtLSFSyncSymbols = append(LSFPreambleSymbols, LSFSyncSymbols...)
	StreamSyncSymbols = []float64{-3, -3, -3, -3, +3, +3, -3, +3} // 0xFF5D
	PacketSyncSymbols = []float64{+3, -3, +3, +3, -3, -3, -3, -3} // 0x75FF
	BERTSyncSymbols   = []float64{-3, +3, -3, -3, +3, +3, +3, +3} // 0xDF55
	EOTMarkerSymbols  = []float64{+3, +3, +3, +3, +3, +3, -3, +3} // 0x555D
)
View Source
var (
	LSFSyncBytes    = []byte{0x55, 0xF7}
	StreamSyncBytes = []byte{0xFF, 0x5D}
	PacketSyncBytes = []byte{0x75, 0xFF}
	BERTSyncBytes   = []byte{0xDF, 0x55}
	EOTMarkerBytes  = []byte{0x55, 0x5D}
)
View Source
var (
	ErrMMDVMReadTimeout         = errors.New("read timeout")
	ErrUnsupportedModemProtocol = errors.New("unsupported MMDVM protocol version")
	ErrModemNAK                 = errors.New("modem returned NAK")
)
View Source
var EncodedDestinationAllBytes = EncodedCallsign{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
View Source
var PacketPuncturePattern = PuncturePattern{true, true, true, true, true, true, true, false}
View Source
var StreamPuncturePattern = PuncturePattern{true, true, true, true, true, true, true, true, true, true, true, false}

Functions

func CRC

func CRC(in []byte) uint16

Calculate CRC value.

func CalculateHammingDistance

func CalculateHammingDistance(a, b uint32) int

CalculateHammingDistance calculates the Hamming distance between two codewords

func CalculateSyndrome

func CalculateSyndrome(codeword uint32) uint16

CalculateSyndrome calculates the syndrome for error detection

func DecodeCallsign

func DecodeCallsign(encoded []byte) (string, error)

func DecodeLICH

func DecodeLICH(inp []SoftBit) []byte

DecodeLICH decodes LICH into a 6-byte array inp: pointer to an array of 96 soft bits

func Encode24

func Encode24(data uint16) uint32

Encode24 encodes a 12-bit value with Golay(24, 12) data: 12-bit input value (right justified) returns: 24-bit Golay codeword

func EncodeLICH

func EncodeLICH(inp []uint8) []byte

EncodeLICH encodes 6 bytes into 12 bytes using Golay encoding

func EuclNorm

func EuclNorm(s1, s2 []Symbol, n int) float64

func GetErrorCorrectionCapability

func GetErrorCorrectionCapability() int

GetErrorCorrectionCapability returns the maximum number of errors that can be corrected

func GetMinimumDistance

func GetMinimumDistance() int

GetMinimumDistance returns the minimum Hamming distance of the code

func HardDecode24

func HardDecode24(codeword uint32) (uint16, error)

HardDecode24 performs hard-decision decoding of a Golay(24,12) codeword This is a simpler version that works with hard bits (0 or 1)

func IntToSoft

func IntToSoft(out []SoftBit, value uint16, size uint8)

IntToSoft converts an integer to soft-valued bit array

func IsValidCodeword

func IsValidCodeword(codeword uint32) bool

IsValidCodeword checks if a 24-bit word is a valid Golay codeword

func NormalizeCallsignModule

func NormalizeCallsignModule(callsign string) string

For regular callsigns, if the callsign ends with a space followed by a module letter, put the module letter in position 9 (the convention) with spaces preceding it

func SoftCalcChecksum

func SoftCalcChecksum(out, value []SoftBit)

SoftCalcChecksum calculates checksum for soft-valued data This follows the C implementation exactly

func SoftDecode24

func SoftDecode24(codeword [24]SoftBit) uint16

SoftDecode24 performs soft decode of Golay(24, 12) codeword

func SoftDetectErrors

func SoftDetectErrors(codeword []SoftBit) uint32

SoftDetectErrors detects errors in a soft-valued Golay(24, 12) codeword

func SoftPopCount

func SoftPopCount(in []uint16, size uint8) uint32

SoftPopCount performs soft-valued equivalent of popcount

func SoftToInt

func SoftToInt(in []SoftBit, size uint8) uint16

SoftToInt converts soft-valued bit array to integer

func SoftXOR

func SoftXOR(out, a, b []SoftBit, size uint8)

SoftXOR performs XOR operation on arrays of soft-valued bits

Types

type Bit

type Bit bool

func ConvolutionalEncode

func ConvolutionalEncode(in []byte, puncturePattern PuncturePattern, finalBit byte) ([]Bit, error)

ConvolutionalEncode takes a slice of bytes and a puncture pattern and returns an a slice of bool with each element representing one bit in the encoded message

in Input bytes puncturePattern the puncture pattern to use finalBit The last bit of the final byte to encode. A number between 0 and 7. (That is, the number of bits from the last byte to use minus one.)

func ConvolutionalEncodeStream

func ConvolutionalEncodeStream(lichBits []Bit, sd StreamDatagram) ([]Bit, error)

func (*Bit) Byte

func (b *Bit) Byte() byte

func (*Bit) Set

func (b *Bit) Set(by byte)

type CC1200Modem

type CC1200Modem struct {
	// contains filtered or unexported fields
}

func NewCC1200Modem

func NewCC1200Modem(
	rxFrequency uint32,
	txFrequency uint32,
	power float32,
	frequencyCorr int16,
	afc bool,
	modemCfg *ini.Section) (*CC1200Modem, error)

func (*CC1200Modem) Close

func (m *CC1200Modem) Close() error

Close the modem

func (*CC1200Modem) Reset

func (m *CC1200Modem) Reset() error

Reset the modem

func (*CC1200Modem) Start

func (m *CC1200Modem) Start() error

func (*CC1200Modem) StartDecoding added in v0.2.0

func (m *CC1200Modem) StartDecoding(sink func(typ uint16, softBits []SoftBit))

func (*CC1200Modem) TransmitPacket

func (m *CC1200Modem) TransmitPacket(p Packet) error

func (*CC1200Modem) TransmitVoiceStream

func (m *CC1200Modem) TransmitVoiceStream(sd StreamDatagram) error

type CC1200ModemV2 added in v0.2.15

type CC1200ModemV2 struct {
	// contains filtered or unexported fields
}

func NewCC1200ModemV2 added in v0.2.15

func NewCC1200ModemV2(
	rxFrequency uint32,
	txFrequency uint32,
	power int8,
	frequencyCorr int16,
	afc bool,
	modemCfg *ini.Section) (*CC1200ModemV2, error)

func (*CC1200ModemV2) Close added in v0.2.15

func (m *CC1200ModemV2) Close() error

Close the modem

func (*CC1200ModemV2) Reset added in v0.2.15

func (m *CC1200ModemV2) Reset() error

Reset the modem

func (*CC1200ModemV2) Start added in v0.2.15

func (m *CC1200ModemV2) Start() error

func (*CC1200ModemV2) StartDecoding added in v0.2.15

func (m *CC1200ModemV2) StartDecoding(sink func(typ uint16, softBits []SoftBit))

func (*CC1200ModemV2) TransmitPacket added in v0.2.15

func (m *CC1200ModemV2) TransmitPacket(p Packet) error

func (*CC1200ModemV2) TransmitVoiceStream added in v0.2.15

func (m *CC1200ModemV2) TransmitVoiceStream(sd StreamDatagram) error

type Converter added in v0.2.10

type Converter[T Number, U Number] struct {
	Transform[T, U]
}

scale samples by a factor

func NewConverter added in v0.2.10

func NewConverter[T Number, U Number](sink chan T) Converter[T, U]

type DCFilter

type DCFilter struct {
	Transform[float64, float64]
	// contains filtered or unexported fields
}

Filter DC from int8 samples by subtracting a moving average

func NewDCFilter

func NewDCFilter(sink chan float64, averageCnt int) (DCFilter, error)

type Decoder

type Decoder struct {
	// contains filtered or unexported fields
}

func NewDecoder

func NewDecoder(
	receivedRFLSF func(lsf LSF, ber float64) error,
	receivedRFStream func(lsf LSF, payload []byte, sid, fn uint16, ber float64) error,
	receivedRFStreamLICH func(lsf LSF, ber float64) error,
	receivedRFStreamEOT func(lsf LSF, sid, fn uint16, ber float64) error,
	receivedRFPacket func(lsf LSF, payload []byte, ber float64) error,
) *Decoder

func (*Decoder) DecodeFrame added in v0.2.0

func (d *Decoder) DecodeFrame(typ uint16, softBits []SoftBit)

type Downsampler

type Downsampler[T any] struct {
	Transform[T, T]
	// contains filtered or unexported fields
}

Downsample a stream by returning one out of each N values

func NewDownsampler

func NewDownsampler[T any](sink chan T, factor int, offset int) (Downsampler[T], error)

type DummyModem

type DummyModem struct {
	In  io.ReadCloser
	Out io.WriteCloser
	// contains filtered or unexported fields
}

func (*DummyModem) Close

func (m *DummyModem) Close() error

func (*DummyModem) Read

func (m *DummyModem) Read(p []byte) (n int, err error)

func (*DummyModem) Reset

func (m *DummyModem) Reset() error

func (*DummyModem) SetAFC

func (m *DummyModem) SetAFC(afc bool) error

func (*DummyModem) SetFreqCorrection

func (m *DummyModem) SetFreqCorrection(corr int16) error

func (*DummyModem) SetRXFreq

func (m *DummyModem) SetRXFreq(freq uint32) error

func (*DummyModem) SetTXFreq

func (m *DummyModem) SetTXFreq(freq uint32) error

func (*DummyModem) SetTXPower

func (m *DummyModem) SetTXPower(dbm float32) error

func (*DummyModem) Start

func (m *DummyModem) Start() error

func (*DummyModem) StartDecoding added in v0.2.0

func (m *DummyModem) StartDecoding(sink func(typ uint16, softBits []SoftBit))

func (*DummyModem) TransmitPacket

func (m *DummyModem) TransmitPacket(p Packet) error

func (*DummyModem) TransmitVoiceStream

func (m *DummyModem) TransmitVoiceStream(sd StreamDatagram) error

func (*DummyModem) Write

func (m *DummyModem) Write(buf []byte) (n int, err error)

type ECD added in v0.1.21

type ECD struct {
	Callsign1 *EncodedCallsign
	Callsign2 *EncodedCallsign
}

func NewECDFromMeta added in v0.1.21

func NewECDFromMeta(meta [14]byte) ECD

func (ECD) String added in v0.1.21

func (e ECD) String() string

type EncodedCallsign

type EncodedCallsign [EncodedCallsignLen]byte

func EncodeCallsign

func EncodeCallsign(callsign string) (*EncodedCallsign, error)

func (EncodedCallsign) Callsign

func (e EncodedCallsign) Callsign() string

type GNSS added in v0.1.21

type GNSS struct {
	DataSource        byte
	StationType       byte
	Radius            byte
	Bearing           uint16
	Latitude          float32
	Longitude         float32
	Altitude          float32
	Speed             float32
	ValidLatLon       bool
	ValidAltitude     bool
	ValidBearingSpeed bool
	ValidRadius       bool
}

func NewGNSSFromMeta added in v0.1.21

func NewGNSSFromMeta(meta [14]byte) *GNSS

func (GNSS) String added in v0.1.21

func (g GNSS) String() string

type Host added in v0.1.7

type Host struct {
	Name   string
	Server string
	Port   uint
}

type Hostfile added in v0.1.7

type Hostfile struct {
	Hosts map[string]Host
}

func NewHostfile added in v0.1.7

func NewHostfile(name string) (*Hostfile, error)

type IIRFilter added in v0.2.10

type IIRFilter struct {
	Transform[float64, float64]
	// contains filtered or unexported fields
}

IIRFilter represents a simple first-order IIR filter

func NewIIRFilter added in v0.2.10

func NewIIRFilter(sink chan float64, b, a []float64) (IIRFilter, error)

NewIIRFilter initializes and returns a new IIR filter

func (*IIRFilter) Source added in v0.2.10

func (t *IIRFilter) Source() chan float64

type LSF

type LSF struct {
	Dst  EncodedCallsign
	Src  EncodedCallsign
	Type [typeLen]byte
	Meta [metaLen]byte
	CRC  [CRCLen]byte
}

Link Setup Frame

func NewEmptyLSF

func NewEmptyLSF() LSF

func NewLSF

func NewLSF(destCall, sourceCall string, t LSFType, dt LSFDataType, can byte) (LSF, error)

func NewLSFFromBytes

func NewLSFFromBytes(buf []byte) *LSF

func NewLSFFromLSD

func NewLSFFromLSD(lsd []byte) *LSF

func (*LSF) CAN

func (l *LSF) CAN() byte

func (*LSF) CalcCRC

func (l *LSF) CalcCRC() uint16

Calculate CRC for this LSF

func (*LSF) CheckCRC

func (l *LSF) CheckCRC() bool

Check if the CRC is correct

func (*LSF) DataType added in v0.1.21

func (l *LSF) DataType() LSFDataType

func (*LSF) ECD added in v0.1.21

func (l *LSF) ECD() *ECD

func (*LSF) EncryptionSubtype added in v0.1.21

func (l *LSF) EncryptionSubtype() byte

func (*LSF) EncryptionType added in v0.1.21

func (l *LSF) EncryptionType() LSFEncryptionType

func (*LSF) GNSS added in v0.1.21

func (l *LSF) GNSS() *GNSS

func (*LSF) LSFType

func (l *LSF) LSFType() LSFType

func (*LSF) SetECD added in v0.2.11

func (l *LSF) SetECD(slot1, slot2 *EncodedCallsign)

Replace META with Extended Callsign Data

func (LSF) String

func (l LSF) String() string

func (*LSF) ToBytes

func (l *LSF) ToBytes() []byte

Convert this LSF to a byte slice suitable for transmission

func (*LSF) ToLSDBytes

func (l *LSF) ToLSDBytes() []byte

Convert this LSF to a byte slice suitable for transmission

type LSFDataType

type LSFDataType byte
const (
	LSFDataTypeReserved LSFDataType = iota
	LSFDataTypeData
	LSFDataTypeVoice
	LSFDataTypeVoiceData
)

func (LSFDataType) String added in v0.1.21

func (t LSFDataType) String() string

type LSFEncryptionType

type LSFEncryptionType byte
const (
	LSFEncryptionTypeNone LSFEncryptionType = iota
	LSFEncryptionTypeScrambler
	LSFEncryptionTypeAES
	LSFEncryptionTypeOther
)

func (LSFEncryptionType) String added in v0.1.21

func (t LSFEncryptionType) String() string

type LSFType

type LSFType byte
const (
	LSFTypePacket LSFType = iota
	LSFTypeStream
)

func (LSFType) String added in v0.1.21

func (t LSFType) String() string

type MMDVMConfig added in v0.2.0

type MMDVMConfig struct {
	// contains filtered or unexported fields
}

type MMDVMModem added in v0.2.0

type MMDVMModem struct {
	// contains filtered or unexported fields
}

func NewMMDVMModem added in v0.2.0

func NewMMDVMModem(
	rxFrequency uint32,
	txFrequency uint32,
	power float32,
	frequencyCorr int16,
	afc bool,
	modemCfg *ini.Section,
	duplex bool) (*MMDVMModem, error)

func (*MMDVMModem) Close added in v0.2.0

func (m *MMDVMModem) Close() error

Close the modem

func (*MMDVMModem) Reset added in v0.2.0

func (m *MMDVMModem) Reset() error

Reset the modem

func (*MMDVMModem) Start added in v0.2.0

func (m *MMDVMModem) Start() error

func (*MMDVMModem) StartDecoding added in v0.2.0

func (m *MMDVMModem) StartDecoding(sink func(typ uint16, softBits []SoftBit))

func (*MMDVMModem) TransmitPacket added in v0.2.0

func (m *MMDVMModem) TransmitPacket(p Packet) error

func (*MMDVMModem) TransmitVoiceStream added in v0.2.0

func (m *MMDVMModem) TransmitVoiceStream(sd StreamDatagram) error

type Modem

type Modem interface {
	StartDecoding(sink func(typ uint16, softBits []SoftBit))
	Start() error
	Reset() error
	Close() error
	TransmitPacket(Packet) error
	TransmitVoiceStream(StreamDatagram) error
}

type Number

type Number interface {
	constraints.Integer | constraints.Float
}

type Packet

type Packet struct {
	LSF     *LSF
	Type    PacketType
	Payload []byte
	CRC     uint16
}

M17 packet

func NewPacket

func NewPacket(dst, src string, t PacketType, data []byte) (*Packet, error)

func NewPacketFromBytes

func NewPacketFromBytes(buf []byte) Packet

func (*Packet) CalcCRC added in v0.2.20

func (p *Packet) CalcCRC() uint16

Calculate CRC

func (*Packet) CheckCRC

func (p *Packet) CheckCRC() bool

Check if the CRC is correct

func (*Packet) Encode

func (p *Packet) Encode() ([]Symbol, error)

func (*Packet) PayloadBytes

func (p *Packet) PayloadBytes() []byte

Convert the payload (type, message and CRC) to a byte slice suitable for transmission

func (Packet) String

func (p Packet) String() string

func (*Packet) ToBytes

func (p *Packet) ToBytes() []byte

Convert this Packet to a byte slice suitable for transmission

type PacketType

type PacketType rune
const (
	PacketTypeRAW     PacketType = 0x00
	PacketTypeAX25    PacketType = 0x01
	PacketTypeAPRS    PacketType = 0x02
	PacketType6LoWPAN PacketType = 0x03
	PacketTypeIPv4    PacketType = 0x04
	PacketTypeSMS     PacketType = 0x05
	PacketTypeWinlink PacketType = 0x06
)

type PayloadBits added in v0.2.0

type PayloadBits [BitsPerPayload]Bit

func InterleaveBits

func InterleaveBits(in *PayloadBits) *PayloadBits

Interleave payload bits.

func NewPayloadBits added in v0.2.0

func NewPayloadBits(bs []Bit) *PayloadBits

func RandomizeBits

func RandomizeBits(bits *PayloadBits) *PayloadBits

type Preamble

type Preamble byte

Preamble type (0 for LSF, 1 for BERT).

type PuncturePattern

type PuncturePattern []Bit

type Relay

type Relay struct {
	Name        string
	Server      string
	Port        uint
	Module      byte
	EncodedName *EncodedCallsign
	// contains filtered or unexported fields
}

func NewRelay

func NewRelay(name string, server string, port uint, module string, callsign string, dashLog *slog.Logger, packetHandler func(Packet) error, streamHandler func(StreamDatagram) error) (*Relay, error)

func (*Relay) Close

func (r *Relay) Close() error

func (*Relay) Connect

func (r *Relay) Connect() error

func (*Relay) SendPacket

func (r *Relay) SendPacket(p Packet) error

func (*Relay) SendStream

func (r *Relay) SendStream(sd StreamDatagram) error

type SampleToSymbol

type SampleToSymbol struct {
	Transform[float64, float32]
	// contains filtered or unexported fields
}

Transform int8 samples to float32 symbols by RRC filtering them

func NewSampleToSymbol

func NewSampleToSymbol(sink chan float64, rrcTaps []float64, scalingCoeff float64) SampleToSymbol

func (*SampleToSymbol) Source

func (t *SampleToSymbol) Source() chan float32

type Scaler

type Scaler[T Number] struct {
	Transform[T, T]
	// contains filtered or unexported fields
}

scale samples by a factor

func NewScaler

func NewScaler[T Number](sink chan T, factor T) Scaler[T]

type SoftBit

type SoftBit uint16

func DeinterleaveSoftBits

func DeinterleaveSoftBits(softBits []SoftBit) []SoftBit

func DerandomizeSoftBits

func DerandomizeSoftBits(softBits []SoftBit) []SoftBit

func SoftBitXOR

func SoftBitXOR(a, b SoftBit) SoftBit

SoftBitXOR performs XOR operation on soft-valued bits This should match the C test expectations exactly

func (SoftBit) String added in v0.2.0

func (b SoftBit) String() string

type StreamDatagram

type StreamDatagram struct {
	StreamID    uint16
	FrameNumber uint16
	LastFrame   bool
	LSF         *LSF
	Payload     [16]byte
}

func NewStreamDatagram

func NewStreamDatagram(streamID uint16, frameNumber uint16, lsf *LSF, payload []byte) StreamDatagram

func NewStreamDatagramFromBytes added in v0.1.23

func NewStreamDatagramFromBytes(buffer []byte) (StreamDatagram, error)

func (StreamDatagram) String added in v0.1.23

func (sd StreamDatagram) String() string

func (StreamDatagram) ToBytes added in v0.1.23

func (sd StreamDatagram) ToBytes() []byte

type Symbol

type Symbol float32

func AppendBits

func AppendBits(out []Symbol, data *PayloadBits) []Symbol

func AppendEOT

func AppendEOT(out []Symbol) []Symbol

Generate symbol stream for the End of Transmission marker.

func AppendPreamble

func AppendPreamble(out []Symbol, typ Preamble) []Symbol

AppendPreamble generates symbol stream for a preamble.

func AppendSyncwordSymbols added in v0.2.0

func AppendSyncwordSymbols(out []Symbol, syncword uint16) []Symbol

AppendSyncwordSymbols generates the symbol stream for a syncword.

type SymbolToSample

type SymbolToSample struct {
	// contains filtered or unexported fields
}

Transform float32 symbols to int8 samples

func NewSymbolToSample

func NewSymbolToSample(rrcTaps []float64, scalingCoeff float32, phaseInvert bool, samplesPerSymbol int) SymbolToSample

func (*SymbolToSample) Transform

func (t *SymbolToSample) Transform(symbols []Symbol) []byte

type Transform

type Transform[I any, O any] struct {
	// contains filtered or unexported fields
}

Generic transformation

func NewTransform

func NewTransform[I any, O any](sink chan I, transform func(I) []O, sourceSize int) Transform[I, O]

func (*Transform[I, O]) Source

func (t *Transform[I, O]) Source() chan O

type ViterbiDecoder

type ViterbiDecoder struct {
	// contains filtered or unexported fields
}

func (*ViterbiDecoder) DecodePunctured

func (v *ViterbiDecoder) DecodePunctured(puncturedSoftBits []SoftBit, puncturePattern PuncturePattern) ([]byte, int)

func (*ViterbiDecoder) Init

func (v *ViterbiDecoder) Init(l int)

Directories

Path Synopsis
cmd
m17-gateway command
m17-message command
m17-text-cli command
modem-emulator command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL