libsstvenc
Asynchronous Analogue SSTV encoder
Loading...
Searching...
No Matches
SSTV encoder
Collaboration diagram for SSTV encoder:

Topics

 SSTV Encoder Phases
 
 SSTV frequency specifications.
 
 SSTV mode specifications.
 
 RGB to YUV conversions (and vice versa).
 
 SSTV VIS header bits
 
 SSTV scan line segments
 

Data Structures

struct  sstvenc_encoder
 
union  sstvenc_encoder::sstvenc_encoder_phase_data
 
struct  sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data
 
struct  sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data
 
struct  sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data
 

Macros

#define SSTVENC_ENCODER_FSK_SEGMENT_BEGIN   (0)
 
#define SSTVENC_ENCODER_FSK_SEGMENT_PREAMBLE   (1)
 
#define SSTVENC_ENCODER_FSK_SEGMENT_ID   (2)
 
#define SSTVENC_ENCODER_FSK_SEGMENT_TAIL   (3)
 
#define SSTVENC_ENCODER_FSK_SEGMENT_DONE   (4)
 

Typedefs

typedef void sstvenc_encoder_callback(struct sstvenc_encoder *const enc)
 

Functions

void sstvenc_encoder_init (struct sstvenc_encoder *const enc, const struct sstvenc_mode *mode, const char *fsk_id, const uint8_t *framebuffer)
 
const struct sstvenc_encoder_pulsesstvenc_encoder_next_pulse (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_new_phase (struct sstvenc_encoder *const enc, uint8_t phase)
 
static void sstvenc_encoder_begin_seq (struct sstvenc_encoder *const enc, const struct sstvenc_encoder_pulse *seq, sstvenc_encoder_callback *on_done)
 
static const struct sstvenc_encoder_pulsesstvenc_encoder_next_seq_pulse (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_vis (struct sstvenc_encoder *const enc)
 
static uint32_t sstvenc_encoder_vis_data_freq (struct sstvenc_encoder *const enc)
 
static uint32_t sstvenc_encoder_vis_parity_freq (struct sstvenc_encoder *const enc)
 
static const struct sstvenc_encoder_pulsesstvenc_encoder_next_vis_pulse (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_image (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_scanline (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_channel (struct sstvenc_encoder *const enc, uint8_t segment, uint8_t ch)
 
static void sstvenc_encoder_next_scan_seg (struct sstvenc_encoder *const enc, uint8_t next_segment)
 
static void sstvenc_encoder_on_initseq_done (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_fsk (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_on_finalseq_done (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_frontporch (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_gap01 (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_gap12 (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_gap23 (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_begin_backporch (struct sstvenc_encoder *const enc)
 
static const struct sstvenc_encoder_pulsesstvenc_encoder_next_channel_pulse (struct sstvenc_encoder *const enc, uint8_t ch)
 
static const struct sstvenc_encoder_pulsesstvenc_encoder_next_image_pulse (struct sstvenc_encoder *const enc)
 
static void sstvenc_encoder_fsk_load_next (struct sstvenc_encoder *const enc)
 
static const struct sstvenc_encoder_pulsesstvenc_encoder_next_fsk_pulse (struct sstvenc_encoder *const enc)
 

Variables

const struct sstvenc_modesstvenc_encoder::mode
 
const char * sstvenc_encoder::fsk_id
 
const uint8_t * sstvenc_encoder::framebuffer
 
const struct sstvenc_encoder_pulsesstvenc_encoder::seq
 
sstvenc_encoder_callbacksstvenc_encoder::seq_done_cb
 
struct sstvenc_encoder_pulse sstvenc_encoder::pulse
 
uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data::bit
 
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data sstvenc_encoder::sstvenc_encoder_phase_data::vis
 
uint16_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::x
 
uint16_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y
 
uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::segment
 
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data sstvenc_encoder::sstvenc_encoder_phase_data::scan
 
uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::segment
 
uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::seg_sz
 
uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::byte
 
uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bv
 
uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bit
 
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data sstvenc_encoder::sstvenc_encoder_phase_data::fsk
 
union sstvenc_encoder::sstvenc_encoder_phase_data sstvenc_encoder::vars
 
uint8_t sstvenc_encoder::phase
 
static const uint8_t sstvenc_encoder_fsk_preamble [] = {0x20, 0x2a}
 
static const uint8_t sstvenc_encoder_fsk_tail [] = {0x01}
 

Detailed Description

This is an asynchronous SSTV encoder that emits frequency/duration pairs to be used with an oscillator (see Oscillator implementation) to produce actual audio samples.

Depending on the SSTV mode it will expect a framebuffer with one of the following forms:

The routines in RGB to YUV conversions (and vice versa). may be useful for converting between RGB and YUV or monochrome modes in your application.

Calling code initialises a context by calling sstvenc_encoder_init then repeatedly calling sstvenc_encoder_next_pulse to compute each SSTV image pulse. Calling code may conclude the state machine is finished when sstvenc_encoder::phase reaches SSTVENC_ENCODER_PHASE_DONE or when sstvenc_encoder_next_pulse returns NULL.


Data Structure Documentation

◆ sstvenc_encoder

struct sstvenc_encoder

SSTV encoder data structure. This encodes the state of the encoder and all the necessary oscillator and pulse shaper structures.

Definition at line 98 of file sstv.h.

Collaboration diagram for sstvenc_encoder:
Data Fields
const uint8_t * framebuffer

The framebuffer holding the image to be sent. The image is assumed to be in the correct format for the SSTV mode, i.e. correct dimensions, channel count and colour space.

For colour SSTV modes, the values are interleaved for each channel, so c0, c1, c2; for the first pixel, then c0, c1, c2 for the second, etc. Use SSTVENC_MODE_GET_CH to determine what channel is what.

const char * fsk_id

The FSK-ID to be appended to the end. NULL for no FSK ID

const struct sstvenc_mode * mode

The SSTV mode being used for encoding.

uint8_t phase

The transmission phase we are in.

struct sstvenc_encoder_pulse pulse

The current pulse being emitted

const struct sstvenc_encoder_pulse * seq

The current pulse sequence being emitted

sstvenc_encoder_callback * seq_done_cb

What to do if the sequence is done?

union sstvenc_encoder_phase_data vars

◆ sstvenc_encoder::sstvenc_encoder_phase_data

union sstvenc_encoder::sstvenc_encoder_phase_data

Definition at line 126 of file sstv.h.

Collaboration diagram for sstvenc_encoder::sstvenc_encoder_phase_data:
Data Fields
struct sstvenc_encoder_phase_fsk_data fsk
struct sstvenc_encoder_phase_scan_data scan
struct sstvenc_encoder_phase_vis_data vis

◆ sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data

struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data

Definition at line 127 of file sstv.h.

Collaboration diagram for sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data:
Data Fields
uint8_t bit

The current bit being sent

◆ sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data

struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data

Definition at line 132 of file sstv.h.

Collaboration diagram for sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data:
Data Fields
uint8_t segment

Scanline segment being emitted

uint16_t x

The current image X position being scanned

uint16_t y

The current image Y position being scanned

◆ sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data

struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data

Definition at line 149 of file sstv.h.

Collaboration diagram for sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data:
Data Fields
uint8_t bit

The current bit of the byte being sent

uint8_t bv

The current byte value being sent

uint8_t byte

The current byte position being sent

uint8_t seg_sz

The current segment length

uint8_t segment

The current byte segment being sent

Macro Definition Documentation

◆ SSTVENC_ENCODER_FSK_SEGMENT_BEGIN

#define SSTVENC_ENCODER_FSK_SEGMENT_BEGIN   (0)

Definition at line 892 of file sstv.c.

Referenced by sstvenc_encoder_begin_fsk(), and sstvenc_encoder_fsk_load_next().

◆ SSTVENC_ENCODER_FSK_SEGMENT_DONE

#define SSTVENC_ENCODER_FSK_SEGMENT_DONE   (4)

◆ SSTVENC_ENCODER_FSK_SEGMENT_ID

#define SSTVENC_ENCODER_FSK_SEGMENT_ID   (2)

Definition at line 894 of file sstv.c.

Referenced by sstvenc_encoder_fsk_load_next().

◆ SSTVENC_ENCODER_FSK_SEGMENT_PREAMBLE

#define SSTVENC_ENCODER_FSK_SEGMENT_PREAMBLE   (1)

Definition at line 893 of file sstv.c.

Referenced by sstvenc_encoder_fsk_load_next().

◆ SSTVENC_ENCODER_FSK_SEGMENT_TAIL

#define SSTVENC_ENCODER_FSK_SEGMENT_TAIL   (3)

Definition at line 895 of file sstv.c.

Referenced by sstvenc_encoder_fsk_load_next().

Typedef Documentation

◆ sstvenc_encoder_callback

typedef void sstvenc_encoder_callback(struct sstvenc_encoder *const enc)

Callback routine for SSTV encoder events.

Definition at line 92 of file sstv.h.

Function Documentation

◆ sstvenc_encoder_begin_backporch()

static void sstvenc_encoder_begin_backporch ( struct sstvenc_encoder *const enc)
static

Set up the state machine to begin sending the back-porch sync pulses at the end of the scan line.

Parameters
[in,out]encSSTV encoder instance

Definition at line 714 of file sstv.c.

714 {
715#ifdef _DEBUG_SSTV
716 printf("%s: begin row %u back porch\n", __func__, enc->vars.scan.y);
717#endif
720 sstvenc_encoder_begin_seq(enc, enc->mode->backporch, NULL);
721}
#define SSTVENC_ENCODER_SCAN_SEGMENT_BACKPORCH
Definition sstv.c:149
const struct sstvenc_mode * mode
Definition sstv.h:100
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data scan
static void sstvenc_encoder_next_scan_seg(struct sstvenc_encoder *const enc, uint8_t next_segment)
Definition sstv.c:723
static void sstvenc_encoder_begin_seq(struct sstvenc_encoder *const enc, const struct sstvenc_encoder_pulse *seq, sstvenc_encoder_callback *on_done)
Definition sstv.c:402
union sstvenc_encoder::sstvenc_encoder_phase_data vars
const struct sstvenc_encoder_pulse * backporch
Definition sstvmode.h:198

References sstvenc_mode::backporch, sstvenc_encoder::mode, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder_begin_seq(), sstvenc_encoder_next_scan_seg(), SSTVENC_ENCODER_SCAN_SEGMENT_BACKPORCH, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_image_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_channel()

static void sstvenc_encoder_begin_channel ( struct sstvenc_encoder *const enc,
uint8_t segment,
uint8_t ch )
static

Set up the state machine for transmitting the given channel of the current scan line.

Parameters
[in,out]encSSTV encoder instance
[in]chSSTV scan line channel being emitted (0-3 inclusive)

Definition at line 586 of file sstv.c.

587 {
588#ifdef _DEBUG_SSTV
589 printf("%s: begin row %u channel %u\n", __func__, enc->vars.scan.y,
590 ch);
591#endif
592 sstvenc_encoder_next_scan_seg(enc, segment);
593 enc->vars.scan.x = 0;
594 enc->pulse.duration_ns
595 = (uint32_t)((((double)enc->mode->scanline_period_ns[ch])
596 / enc->mode->width)
597 + 0.5);
598#ifdef _DEBUG_SSTV
599 printf("%s: %" PRIu32 " ns per pixel\n", __func__,
600 enc->pulse.duration_ns);
601#endif
602}
struct sstvenc_encoder_pulse pulse
Definition sstv.h:124
uint16_t width
Definition sstvmode.h:215
uint32_t scanline_period_ns[4]
Definition sstvmode.h:210

References sstvenc_encoder_pulse::duration_ns, sstvenc_encoder::mode, sstvenc_encoder::pulse, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_mode::scanline_period_ns, sstvenc_encoder_next_scan_seg(), sstvenc_encoder::vars, sstvenc_mode::width, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::x, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_image_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_frontporch()

static void sstvenc_encoder_begin_frontporch ( struct sstvenc_encoder *const enc)
static

Set up the state machine to begin sending the front-porch sync pulses at the beginning of the scan line.

Parameters
[in,out]encSSTV encoder instance

Definition at line 677 of file sstv.c.

677 {
678#ifdef _DEBUG_SSTV
679 printf("%s: begin row %u front porch\n", __func__, enc->vars.scan.y);
680#endif
683 sstvenc_encoder_begin_seq(enc, enc->mode->frontporch, NULL);
684}
#define SSTVENC_ENCODER_SCAN_SEGMENT_FRONTPORCH
Definition sstv.c:108
const struct sstvenc_encoder_pulse * frontporch
Definition sstvmode.h:173

References sstvenc_mode::frontporch, sstvenc_encoder::mode, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder_begin_seq(), sstvenc_encoder_next_scan_seg(), SSTVENC_ENCODER_SCAN_SEGMENT_FRONTPORCH, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_begin_scanline().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_fsk()

static void sstvenc_encoder_begin_fsk ( struct sstvenc_encoder *const enc)
static

Set up the state machine for sending the FSK ID.

Parameters
[in,out]encSSTV encoder instance

Definition at line 976 of file sstv.c.

976 {
978 enc->vars.fsk.byte = 0;
979 enc->vars.fsk.bit = 0;
980
981 if (enc->fsk_id) {
982#ifdef _DEBUG_SSTV
983 printf("%s: initialise FSK state\n", __func__);
984#endif
987 } else {
988#ifdef _DEBUG_SSTV
989 printf("%s: no FSK defined\n", __func__);
990#endif
992 }
993}
#define SSTVENC_ENCODER_PHASE_FSK
Definition sstv.h:77
const char * fsk_id
Definition sstv.h:103
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data fsk
#define SSTVENC_ENCODER_FSK_SEGMENT_BEGIN
Definition sstv.c:892
static void sstvenc_encoder_fsk_load_next(struct sstvenc_encoder *const enc)
Definition sstv.c:900
#define SSTVENC_ENCODER_FSK_SEGMENT_DONE
Definition sstv.c:896
static void sstvenc_encoder_new_phase(struct sstvenc_encoder *const enc, uint8_t phase)
Definition sstv.c:384

References sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bit, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::byte, sstvenc_encoder::sstvenc_encoder_phase_data::fsk, sstvenc_encoder::fsk_id, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::segment, sstvenc_encoder_fsk_load_next(), SSTVENC_ENCODER_FSK_SEGMENT_BEGIN, SSTVENC_ENCODER_FSK_SEGMENT_DONE, sstvenc_encoder_new_phase(), SSTVENC_ENCODER_PHASE_FSK, and sstvenc_encoder::vars.

Referenced by sstvenc_encoder_on_finalseq_done().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_gap01()

static void sstvenc_encoder_begin_gap01 ( struct sstvenc_encoder *const enc)
static

Set up the state machine to begin sending the sync pulses that separate channels 0 and 1.

Parameters
[in,out]encSSTV encoder instance

Definition at line 686 of file sstv.c.

686 {
687#ifdef _DEBUG_SSTV
688 printf("%s: begin row %u gap 0/1\n", __func__, enc->vars.scan.y);
689#endif
692 sstvenc_encoder_begin_seq(enc, enc->mode->gap01, NULL);
693}
#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP01
Definition sstv.c:118
const struct sstvenc_encoder_pulse * gap01
Definition sstvmode.h:179

References sstvenc_mode::gap01, sstvenc_encoder::mode, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder_begin_seq(), sstvenc_encoder_next_scan_seg(), SSTVENC_ENCODER_SCAN_SEGMENT_GAP01, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_image_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_gap12()

static void sstvenc_encoder_begin_gap12 ( struct sstvenc_encoder *const enc)
static

Set up the state machine to begin sending the sync pulses that separate channels 1 and 2.

Parameters
[in,out]encSSTV encoder instance

Definition at line 695 of file sstv.c.

695 {
696#ifdef _DEBUG_SSTV
697 printf("%s: begin row %u gap 1/2\n", __func__, enc->vars.scan.y);
698#endif
701 sstvenc_encoder_begin_seq(enc, enc->mode->gap12, NULL);
702}
#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP12
Definition sstv.c:128
const struct sstvenc_encoder_pulse * gap12
Definition sstvmode.h:185

References sstvenc_mode::gap12, sstvenc_encoder::mode, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder_begin_seq(), sstvenc_encoder_next_scan_seg(), SSTVENC_ENCODER_SCAN_SEGMENT_GAP12, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_image_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_gap23()

static void sstvenc_encoder_begin_gap23 ( struct sstvenc_encoder *const enc)
static

Set up the state machine to begin sending the sync pulses that separate channels 2 and 3.

Parameters
[in,out]encSSTV encoder instance

Definition at line 704 of file sstv.c.

704 {
705#ifdef _DEBUG_SSTV
706 printf("%s: begin row %u gap 2/3\n", __func__, enc->vars.scan.y);
707#endif
710 sstvenc_encoder_begin_seq(enc, enc->mode->gap23, NULL);
711}
#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP23
Definition sstv.c:138
const struct sstvenc_encoder_pulse * gap23
Definition sstvmode.h:191

References sstvenc_mode::gap23, sstvenc_encoder::mode, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder_begin_seq(), sstvenc_encoder_next_scan_seg(), SSTVENC_ENCODER_SCAN_SEGMENT_GAP23, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_image_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_image()

static void sstvenc_encoder_begin_image ( struct sstvenc_encoder *const enc)
static

Set up the state machine for the beginning of the image scan.

Parameters
[in,out]encSSTV encoder instance

Definition at line 569 of file sstv.c.

569 {
570#ifdef _DEBUG_SSTV
571 printf("%s: begin image scan\n", __func__);
572#endif
574 enc->vars.scan.y = 0;
576}
#define SSTVENC_ENCODER_PHASE_SCAN
Definition sstv.h:71
static void sstvenc_encoder_begin_scanline(struct sstvenc_encoder *const enc)
Definition sstv.c:579
uint8_t phase
Definition sstv.h:180

References sstvenc_encoder::phase, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder_begin_scanline(), SSTVENC_ENCODER_PHASE_SCAN, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_pulse(), and sstvenc_encoder_on_initseq_done().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_scanline()

static void sstvenc_encoder_begin_scanline ( struct sstvenc_encoder *const enc)
static

Set up the state machine for the beginning of a single scan line.

Parameters
[in,out]encSSTV encoder instance

Definition at line 579 of file sstv.c.

579 {
580#ifdef _DEBUG_SSTV
581 printf("%s: begin row %u\n", __func__, enc->vars.scan.y);
582#endif
584}
static void sstvenc_encoder_begin_frontporch(struct sstvenc_encoder *const enc)
Definition sstv.c:677

References sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder_begin_frontporch(), sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_begin_image(), and sstvenc_encoder_next_image_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_begin_seq()

static void sstvenc_encoder_begin_seq ( struct sstvenc_encoder *const enc,
const struct sstvenc_encoder_pulse * seq,
sstvenc_encoder_callback * on_done )
static

Begin a pulse sequence.

Parameters
[in,out]encSSTV encoder instance
[in]seqPulse sequence, terminated with a 0ns "pulse".
[in]on_doneCallback to run when the pulse sequence ends.

Definition at line 402 of file sstv.c.

404 {
405 enc->seq = seq;
406 if ((!enc->seq) || (!enc->seq->duration_ns)) {
407#ifdef _DEBUG_SSTV
408 printf("%s: empty sequence\n", __func__);
409#endif
410 if (on_done) {
411#ifdef _DEBUG_SSTV
412 printf("%s: calling on_done callback\n", __func__);
413#endif
414 /* Nothing to do */
415 on_done(enc);
416 }
417 } else {
418#ifdef _DEBUG_SSTV
419 printf("%s: begin sequence %p\n", __func__, (void*)seq);
420#endif
421 enc->seq_done_cb = on_done;
422 }
423}
sstvenc_encoder_callback * seq_done_cb
Definition sstv.h:121
const struct sstvenc_encoder_pulse * seq
Definition sstv.h:118

References sstvenc_encoder_pulse::duration_ns, sstvenc_encoder::seq, and sstvenc_encoder::seq_done_cb.

Referenced by sstvenc_encoder_begin_backporch(), sstvenc_encoder_begin_frontporch(), sstvenc_encoder_begin_gap01(), sstvenc_encoder_begin_gap12(), sstvenc_encoder_begin_gap23(), and sstvenc_encoder_next_pulse().

Here is the caller graph for this function:

◆ sstvenc_encoder_begin_vis()

static void sstvenc_encoder_begin_vis ( struct sstvenc_encoder *const enc)
static

Start sending the VIS header.

Parameters
[in,out]encSSTV encoder instance

Definition at line 453 of file sstv.c.

453 {
454#ifdef _DEBUG_SSTV
455 printf("%s: begin sending VIS header\n", __func__);
456#endif
459}
#define SSTVENC_ENCODER_PHASE_VIS
Definition sstv.h:60
#define SSTVENC_VIS_BIT_START1
Definition sstv.c:27
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data vis

References sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data::bit, sstvenc_encoder::phase, SSTVENC_ENCODER_PHASE_VIS, SSTVENC_VIS_BIT_START1, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::vis.

Referenced by sstvenc_encoder_next_pulse().

Here is the caller graph for this function:

◆ sstvenc_encoder_fsk_load_next()

static void sstvenc_encoder_fsk_load_next ( struct sstvenc_encoder *const enc)
static

Determine the value of the next (6-bit) FSK byte to transmit and load it into the state machine.

Parameters
[in,out]encSSTV encoder instance

Definition at line 900 of file sstv.c.

900 {
901 switch (enc->vars.fsk.segment) {
903#ifdef _DEBUG_SSTV
904 printf("%s: load FSK preamble\n", __func__);
905#endif
907 enc->vars.fsk.byte = 0;
909 /* Fall-thru */
911 if (enc->vars.fsk.byte < enc->vars.fsk.seg_sz) {
912 enc->vars.fsk.bv
914 .byte];
915 enc->vars.fsk.bit = 0;
916#ifdef _DEBUG_SSTV
917 printf("%s: preamble byte 0x%02x\n", __func__,
918 enc->vars.fsk.bv);
919#endif
920 break;
921 } else {
922 enc->vars.fsk.segment
924 enc->vars.fsk.seg_sz = strlen(enc->fsk_id);
925 enc->vars.fsk.byte = 0;
926#ifdef _DEBUG_SSTV
927 printf("%s: end of preamble, load FSK ID byte 0\n",
928 __func__);
929#endif
930 }
931 /* Fall-thru */
933 if (enc->vars.fsk.byte < enc->vars.fsk.seg_sz) {
934#ifdef _DEBUG_SSTV
935 printf("%s: FSK ID byte %u = 0x%02x\n", __func__,
936 enc->vars.fsk.byte, enc->vars.fsk.bv);
937#endif
938 enc->vars.fsk.bv
939 = (uint8_t)(enc->fsk_id[enc->vars.fsk.byte])
940 - 0x20;
941 enc->vars.fsk.bit = 0;
942 break;
943 } else {
944#ifdef _DEBUG_SSTV
945 printf("%s: end of FSK ID, load FSK TAIL byte 0\n",
946 __func__);
947#endif
948 enc->vars.fsk.segment
950 enc->vars.fsk.seg_sz
951 = sizeof(sstvenc_encoder_fsk_tail);
952 enc->vars.fsk.byte = 0;
953 }
954 /* Fall-thru */
956 if (enc->vars.fsk.byte < enc->vars.fsk.seg_sz) {
957#ifdef _DEBUG_SSTV
958 printf("%s: FSK TAIL byte %u = 0x%02x\n", __func__,
959 enc->vars.fsk.byte, enc->vars.fsk.bv);
960#endif
961 enc->vars.fsk.bv
963 enc->vars.fsk.bit = 0;
964 break;
965 } else {
966#ifdef _DEBUG_SSTV
967 printf("%s: end of FSK TAIL\n", __func__);
968#endif
969 enc->vars.fsk.segment
971 enc->vars.fsk.byte = 0;
972 }
973 }
974}
#define SSTVENC_ENCODER_FSK_SEGMENT_PREAMBLE
Definition sstv.c:893
#define SSTVENC_ENCODER_FSK_SEGMENT_TAIL
Definition sstv.c:895
static const uint8_t sstvenc_encoder_fsk_tail[]
Definition sstv.c:898
#define SSTVENC_ENCODER_FSK_SEGMENT_ID
Definition sstv.c:894
static const uint8_t sstvenc_encoder_fsk_preamble[]
Definition sstv.c:897

References sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bit, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bv, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::byte, sstvenc_encoder::sstvenc_encoder_phase_data::fsk, sstvenc_encoder::fsk_id, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::seg_sz, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::segment, sstvenc_encoder_fsk_preamble, SSTVENC_ENCODER_FSK_SEGMENT_BEGIN, SSTVENC_ENCODER_FSK_SEGMENT_DONE, SSTVENC_ENCODER_FSK_SEGMENT_ID, SSTVENC_ENCODER_FSK_SEGMENT_PREAMBLE, SSTVENC_ENCODER_FSK_SEGMENT_TAIL, sstvenc_encoder_fsk_tail, and sstvenc_encoder::vars.

Referenced by sstvenc_encoder_begin_fsk(), and sstvenc_encoder_next_fsk_pulse().

Here is the caller graph for this function:

◆ sstvenc_encoder_init()

void sstvenc_encoder_init ( struct sstvenc_encoder *const enc,
const struct sstvenc_mode * mode,
const char * fsk_id,
const uint8_t * framebuffer )

Initialise the SSTV encoder with the given parameters.

Parameters
[in,out]encSSTV encoder context to initialise
[in]modeSSTV mode to encode
[in]fsk_idFSK ID to send at the end, NULL to disable.
[in]framebufferFramebuffer data representing the image.

Definition at line 392 of file sstv.c.

394 {
395 memset(enc, 0, sizeof(struct sstvenc_encoder));
396 enc->mode = mode;
397 enc->fsk_id = fsk_id;
398 enc->framebuffer = framebuffer;
400}
#define SSTVENC_ENCODER_PHASE_INIT
Definition sstv.h:57
const uint8_t * framebuffer
Definition sstv.h:115

References sstvenc_encoder::framebuffer, sstvenc_encoder::fsk_id, sstvenc_encoder::mode, sstvenc_encoder::phase, and SSTVENC_ENCODER_PHASE_INIT.

Referenced by sstvenc_modulator_init().

Here is the caller graph for this function:

◆ sstvenc_encoder_new_phase()

static void sstvenc_encoder_new_phase ( struct sstvenc_encoder *const enc,
uint8_t phase )
static

Transition the encoder to the next phase. Used as a debugging attachment point in development.

Parameters
[out]encSSTV encoder context
[in]phaseNew phase, SSTV Encoder Phases

Definition at line 384 of file sstv.c.

385 {
386#ifdef _DEBUG_SSTV
387 printf("%s: entering phase 0x%02x\n", __func__, phase);
388#endif
389 enc->phase = phase;
390}

References sstvenc_encoder::phase.

Referenced by sstvenc_encoder_begin_fsk(), and sstvenc_encoder_next_pulse().

Here is the caller graph for this function:

◆ sstvenc_encoder_next_channel_pulse()

static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_channel_pulse ( struct sstvenc_encoder *const enc,
uint8_t ch )
static

Compute the frequency of the next pulse for the current pixel in the indicated scan line.

Parameters
[in,out]encSSTV encoder instance
[in]chScan line channel (0-3 inclusive)
Returns
Pointer to SSTV pixel pulse.
Return values
NULLEnd of scan segment.

Definition at line 605 of file sstv.c.

606 {
607
608 if (enc->vars.scan.x >= enc->mode->width) {
609 /* End of the channel */
610 return NULL;
611 }
612
613 uint32_t idx = sstvenc_get_pixel_posn(enc->mode, enc->vars.scan.x,
614 enc->vars.scan.y);
615 uint8_t value;
616
619 const uint16_t row_length = 3 * enc->mode->width;
620 assert(!(enc->vars.scan.y % 2));
621
622 switch (
625 /* Channel not used */
626 return NULL;
627 case SSTVENC_CSO_CH_Y:
628 value = enc->framebuffer[idx];
629 break;
631 value = enc->framebuffer[idx + row_length];
632 break;
633 case SSTVENC_CSO_CH_U:
634 value = (enc->framebuffer[idx + 1]
635 + enc->framebuffer[idx + row_length + 1])
636 / 2.0;
637 break;
638 case SSTVENC_CSO_CH_V:
639 value = (enc->framebuffer[idx + 2]
640 + enc->framebuffer[idx + row_length + 2])
641 / 2.0;
642 break;
643 default:
644 value = 0.0;
645 }
646 break;
647 }
648 default:
649 switch (
652 /* Channel not used */
653 return NULL;
654 case SSTVENC_CSO_CH_Y:
655 case SSTVENC_CSO_CH_R:
656 value = enc->framebuffer[idx];
657 break;
658 case SSTVENC_CSO_CH_U:
659 case SSTVENC_CSO_CH_G:
660 value = enc->framebuffer[idx + 1];
661 break;
662 case SSTVENC_CSO_CH_V:
663 case SSTVENC_CSO_CH_B:
664 value = enc->framebuffer[idx + 2];
665 break;
666 default:
667 value = 0.0;
668 }
669 }
670
671 enc->pulse.frequency = sstvenc_level_freq(value);
672 enc->vars.scan.x++;
673 return &(enc->pulse);
674}
#define SSTVENC_CSO_CH_NONE
Definition sstvmode.h:86
#define SSTVENC_CSO_CH_R
Definition sstvmode.h:90
#define SSTVENC_CSO_CH_B
Definition sstvmode.h:92
#define SSTVENC_CSO_CH_Y
Definition sstvmode.h:87
#define SSTVENC_CSO_CH_G
Definition sstvmode.h:91
#define SSTVENC_CSO_CH_U
Definition sstvmode.h:88
#define SSTVENC_CSO_CH_Y2
Definition sstvmode.h:93
#define SSTVENC_CSO_CH_V
Definition sstvmode.h:89
#define SSTVENC_CSO_MODE_YUV2
Definition sstvmode.h:75
#define SSTVENC_MODE_GET_CH(n, mode)
Definition sstvmode.h:108
#define SSTVENC_CSO_MASK_MODE
Definition sstvmode.h:45
uint16_t sstvenc_level_freq(uint8_t level)
Definition sstvfreq.c:13
uint16_t colour_space_order
Definition sstvmode.h:226
uint32_t sstvenc_get_pixel_posn(const struct sstvenc_mode *const mode, uint16_t x, uint16_t y)
Definition sstvmode.c:704

References sstvenc_mode::colour_space_order, sstvenc_encoder::framebuffer, sstvenc_encoder_pulse::frequency, sstvenc_encoder::mode, sstvenc_encoder::pulse, sstvenc_encoder::sstvenc_encoder_phase_data::scan, SSTVENC_CSO_CH_B, SSTVENC_CSO_CH_G, SSTVENC_CSO_CH_NONE, SSTVENC_CSO_CH_R, SSTVENC_CSO_CH_U, SSTVENC_CSO_CH_V, SSTVENC_CSO_CH_Y, SSTVENC_CSO_CH_Y2, SSTVENC_CSO_MASK_MODE, SSTVENC_CSO_MODE_YUV2, sstvenc_get_pixel_posn(), sstvenc_level_freq(), SSTVENC_MODE_GET_CH, sstvenc_encoder::vars, sstvenc_mode::width, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::x, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_image_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_next_fsk_pulse()

static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_fsk_pulse ( struct sstvenc_encoder *const enc)
static

Compute the frequency of the next pulse for the FSK ID according to the state machine.

Parameters
[in,out]encSSTV encoder instance
Returns
Pointer to FSK pulse.
Return values
NULLEnd of FSK ID.

Definition at line 996 of file sstv.c.

996 {
997 if (enc->vars.fsk.bit >= 6) {
998#ifdef _DEBUG_SSTV
999 printf("%s: end of FSK byte\n", __func__);
1000#endif
1001 enc->vars.fsk.byte++;
1003 }
1004
1006 /* This is the end of the FSK ID */
1007#ifdef _DEBUG_SSTV
1008 printf("%s: end of FSK\n", __func__);
1009#endif
1010 return NULL;
1011 }
1012
1013 /* Next bit */
1014 if (enc->vars.fsk.bv & (1 << enc->vars.fsk.bit)) {
1015#ifdef _DEBUG_SSTV
1016 printf("%s: FSK bit value 1\n", __func__);
1017#endif
1019 } else {
1020#ifdef _DEBUG_SSTV
1021 printf("%s: FSK bit value 0\n", __func__);
1022#endif
1024 }
1026 enc->vars.fsk.bit++;
1027
1028 return &(enc->pulse);
1029}
#define SSTVENC_FREQ_FSKID_BIT1
Definition sstvfreq.h:25
#define SSTVENC_FREQ_FSKID_BIT0
Definition sstvfreq.h:26
#define SSTVENC_PERIOD_FSKID_BIT
Definition sstvmode.h:24

References sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bit, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bv, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::byte, sstvenc_encoder_pulse::duration_ns, sstvenc_encoder_pulse::frequency, sstvenc_encoder::sstvenc_encoder_phase_data::fsk, sstvenc_encoder::pulse, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::segment, sstvenc_encoder_fsk_load_next(), SSTVENC_ENCODER_FSK_SEGMENT_DONE, SSTVENC_FREQ_FSKID_BIT0, SSTVENC_FREQ_FSKID_BIT1, SSTVENC_PERIOD_FSKID_BIT, and sstvenc_encoder::vars.

Referenced by sstvenc_encoder_next_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_next_image_pulse()

static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_image_pulse ( struct sstvenc_encoder *const enc)
static

Compute the frequency of the next pulse for the image according to the state machine.

Parameters
[in,out]encSSTV encoder instance
Returns
Pointer to SSTV image pulse.
Return values
NULLEnd of image scan.

Definition at line 740 of file sstv.c.

740 {
741 const struct sstvenc_encoder_pulse* pulse = NULL;
742restart:
743 switch (enc->vars.scan.segment) {
746#ifdef _DEBUG_SSTV
747 printf("%s: front porch pulse = %p (*, %u)\n", __func__,
748 (void*)pulse, enc->vars.scan.y);
749#endif
750 if (pulse) {
751 return pulse;
752 }
753 /* Fall-thru */
758#ifdef _DEBUG_SSTV
759 printf("%s: ch0 pulse = %p (%u, %u)\n", __func__,
760 (void*)pulse, enc->vars.scan.x, enc->vars.scan.y);
761#endif
762 if (pulse) {
763 return pulse;
764 }
765 /* Fall-thru */
769#ifdef _DEBUG_SSTV
770 printf("%s: gap 0/1 pulse = %p (*, %u)\n", __func__,
771 (void*)pulse, enc->vars.scan.y);
772#endif
773 if (pulse) {
774 return pulse;
775 }
776 /* Fall-thru */
781#ifdef _DEBUG_SSTV
782 printf("%s: ch1 pulse = %p (%u, %u)\n", __func__,
783 (void*)pulse, enc->vars.scan.x, enc->vars.scan.y);
784#endif
785 if (pulse) {
786 return pulse;
787 }
788 /* Fall-thru */
792#ifdef _DEBUG_SSTV
793 printf("%s: gap 1/2 pulse = %p (*, %u)\n", __func__,
794 (void*)pulse, enc->vars.scan.y);
795#endif
796 if (pulse) {
797 return pulse;
798 }
799 /* Fall-thru */
804#ifdef _DEBUG_SSTV
805 printf("%s: ch2 pulse = %p (%u, %u)\n", __func__,
806 (void*)pulse, enc->vars.scan.x, enc->vars.scan.y);
807#endif
808 if (pulse) {
809 return pulse;
810 }
811 /* Fall-thru */
815#ifdef _DEBUG_SSTV
816 printf("%s: gap 2/3 pulse = %p (*, %u)\n", __func__,
817 (void*)pulse, enc->vars.scan.y);
818#endif
819 if (pulse) {
820 return pulse;
821 }
822 /* Fall-thru */
829#ifdef _DEBUG_SSTV
830 printf("%s: ch3 pulse = %p (%u, %u)\n", __func__,
831 (void*)pulse, enc->vars.scan.x, enc->vars.scan.y);
832#endif
833 if (pulse) {
834 return pulse;
835 }
836 /* Fall-thru */
839#ifdef _DEBUG_SSTV
840 printf("%s: back porch pulse = %p (*, %u)\n", __func__,
841 (void*)pulse, enc->vars.scan.y);
842#endif
844#ifdef _DEBUG_SSTV
845 printf("%s: back porch pulse = %p\n", __func__, (void*)pulse);
846#endif
847 if (pulse) {
848 return pulse;
849 }
850 /* Fall-thru */
851 default:
852#ifdef _DEBUG_SSTV
853 printf("%s: end of scan line\n", __func__);
854#endif
857 break;
858 }
859
860 /* If we reach here, that's the end of the scan line */
861 enc->vars.scan.x = 0;
864#ifdef _DEBUG_SSTV
865 printf("%s: YUV2 increment two rows\n", __func__);
866#endif
867 enc->vars.scan.y += 2;
868 break;
869 default:
870#ifdef _DEBUG_SSTV
871 printf("%s: increment single row\n", __func__);
872#endif
873 enc->vars.scan.y++;
874 }
875
876 if (enc->vars.scan.y < enc->mode->height) {
877 /* Go again */
878#ifdef _DEBUG_SSTV
879 printf("%s: repeat for row %u\n", __func__, enc->vars.scan.y);
880#endif
882 goto restart;
883 }
884
885 /* That's it! */
886#ifdef _DEBUG_SSTV
887 printf("%s: end of image\n", __func__);
888#endif
889 return NULL;
890}
#define SSTVENC_ENCODER_SCAN_SEGMENT_CH0
Definition sstv.c:113
#define SSTVENC_ENCODER_SCAN_SEGMENT_NEXT
Definition sstv.c:154
#define SSTVENC_ENCODER_SCAN_SEGMENT_CH3
Definition sstv.c:143
#define SSTVENC_ENCODER_SCAN_SEGMENT_CH1
Definition sstv.c:123
#define SSTVENC_ENCODER_SCAN_SEGMENT_CH2
Definition sstv.c:133
static void sstvenc_encoder_begin_gap23(struct sstvenc_encoder *const enc)
Definition sstv.c:704
static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_seq_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:426
static void sstvenc_encoder_begin_channel(struct sstvenc_encoder *const enc, uint8_t segment, uint8_t ch)
Definition sstv.c:586
static void sstvenc_encoder_begin_gap01(struct sstvenc_encoder *const enc)
Definition sstv.c:686
static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_channel_pulse(struct sstvenc_encoder *const enc, uint8_t ch)
Definition sstv.c:605
static void sstvenc_encoder_begin_gap12(struct sstvenc_encoder *const enc)
Definition sstv.c:695
static void sstvenc_encoder_begin_backporch(struct sstvenc_encoder *const enc)
Definition sstv.c:714
uint16_t height
Definition sstvmode.h:220

References sstvenc_mode::colour_space_order, sstvenc_mode::height, sstvenc_encoder::mode, sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::segment, SSTVENC_CSO_MASK_MODE, SSTVENC_CSO_MODE_YUV2, sstvenc_encoder_begin_backporch(), sstvenc_encoder_begin_channel(), sstvenc_encoder_begin_gap01(), sstvenc_encoder_begin_gap12(), sstvenc_encoder_begin_gap23(), sstvenc_encoder_begin_scanline(), sstvenc_encoder_next_channel_pulse(), sstvenc_encoder_next_scan_seg(), sstvenc_encoder_next_seq_pulse(), SSTVENC_ENCODER_SCAN_SEGMENT_BACKPORCH, SSTVENC_ENCODER_SCAN_SEGMENT_CH0, SSTVENC_ENCODER_SCAN_SEGMENT_CH1, SSTVENC_ENCODER_SCAN_SEGMENT_CH2, SSTVENC_ENCODER_SCAN_SEGMENT_CH3, SSTVENC_ENCODER_SCAN_SEGMENT_FRONTPORCH, SSTVENC_ENCODER_SCAN_SEGMENT_GAP01, SSTVENC_ENCODER_SCAN_SEGMENT_GAP12, SSTVENC_ENCODER_SCAN_SEGMENT_GAP23, SSTVENC_ENCODER_SCAN_SEGMENT_NEXT, sstvenc_encoder::vars, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::x, and sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::y.

Referenced by sstvenc_encoder_next_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_next_pulse()

const struct sstvenc_encoder_pulse * sstvenc_encoder_next_pulse ( struct sstvenc_encoder *const enc)

Compute the next pulse to be emitted. This value returns NULL when there are no more pulses to transmit.

Definition at line 1032 of file sstv.c.

1032 {
1033 const struct sstvenc_encoder_pulse* pulse = NULL;
1034 switch (enc->phase) {
1036#ifdef _DEBUG_SSTV
1037 printf("%s: initialise encoder\n", __func__);
1038#endif
1040 /* Fall-thru */
1042#ifdef _DEBUG_SSTV
1043 printf("%s: next VIS pulse\n", __func__);
1044#endif
1045 pulse = sstvenc_encoder_next_vis_pulse(enc);
1046 if (pulse) {
1047 break;
1048 } else {
1050 enc, enc->mode->initseq,
1052 }
1053 /* Fall-thru */
1054#ifdef _DEBUG_SSTV
1055 printf("%s: end of VIS\n", __func__);
1056#endif
1058 pulse = sstvenc_encoder_next_seq_pulse(enc);
1059 if (pulse) {
1060 break;
1061 } else {
1063 }
1064 /* Fall-thru */
1065#ifdef _DEBUG_SSTV
1066 printf("%s: end of init sequence\n", __func__);
1067#endif
1068 break;
1071 if (pulse) {
1072 break;
1073 } else {
1075 enc, enc->mode->finalseq,
1077 }
1078#ifdef _DEBUG_SSTV
1079 printf("%s: end of image scan\n", __func__);
1080#endif
1081 /* Fall-thru */
1083 pulse = sstvenc_encoder_next_seq_pulse(enc);
1084 if (pulse) {
1085 break;
1086 }
1087#ifdef _DEBUG_SSTV
1088 printf("%s: end of final sequence\n", __func__);
1089#endif
1090 /* Fall-thru */
1092 pulse = sstvenc_encoder_next_fsk_pulse(enc);
1093 if (pulse) {
1094 break;
1095 }
1096 /* Fall-thru */
1097#ifdef _DEBUG_SSTV
1098 printf("%s: end of FSK ID\n", __func__);
1099#endif
1100 default:
1102 break;
1103 }
1104
1105 return pulse;
1106}
#define SSTVENC_ENCODER_PHASE_FINALSEQ
Definition sstv.h:74
#define SSTVENC_ENCODER_PHASE_INITSEQ
Definition sstv.h:63
#define SSTVENC_ENCODER_PHASE_DONE
Definition sstv.h:80
static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_vis_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:488
static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_image_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:740
static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_fsk_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:996
static void sstvenc_encoder_on_initseq_done(struct sstvenc_encoder *const enc)
Definition sstv.c:562
static void sstvenc_encoder_on_finalseq_done(struct sstvenc_encoder *const enc)
Definition sstv.c:732
static void sstvenc_encoder_begin_vis(struct sstvenc_encoder *const enc)
Definition sstv.c:453
static void sstvenc_encoder_begin_image(struct sstvenc_encoder *const enc)
Definition sstv.c:569
const struct sstvenc_encoder_pulse * finalseq
Definition sstvmode.h:204
const struct sstvenc_encoder_pulse * initseq
Definition sstvmode.h:166

References sstvenc_mode::finalseq, sstvenc_mode::initseq, sstvenc_encoder::mode, sstvenc_encoder::phase, sstvenc_encoder_begin_image(), sstvenc_encoder_begin_seq(), sstvenc_encoder_begin_vis(), sstvenc_encoder_new_phase(), sstvenc_encoder_next_fsk_pulse(), sstvenc_encoder_next_image_pulse(), sstvenc_encoder_next_seq_pulse(), sstvenc_encoder_next_vis_pulse(), sstvenc_encoder_on_finalseq_done(), sstvenc_encoder_on_initseq_done(), SSTVENC_ENCODER_PHASE_DONE, SSTVENC_ENCODER_PHASE_FINALSEQ, SSTVENC_ENCODER_PHASE_FSK, SSTVENC_ENCODER_PHASE_INIT, SSTVENC_ENCODER_PHASE_INITSEQ, SSTVENC_ENCODER_PHASE_SCAN, and SSTVENC_ENCODER_PHASE_VIS.

Referenced by sstvenc_modulator_next_tone().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_next_scan_seg()

static void sstvenc_encoder_next_scan_seg ( struct sstvenc_encoder *const enc,
uint8_t next_segment )
static

Initialise the state for the next scan segment. Used as a debugging attachment point in development.

Parameters
[in,out]encSSTV encoder instance
[in]next_segmentThe next scan line segment. SSTV scan line segments

Definition at line 723 of file sstv.c.

724 {
725#ifdef _DEBUG_SSTV
726 printf("%s: entering segment 0x%02x\n", __func__, next_segment);
727#endif
728 enc->vars.scan.segment = next_segment;
729}

References sstvenc_encoder::sstvenc_encoder_phase_data::scan, sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::segment, and sstvenc_encoder::vars.

Referenced by sstvenc_encoder_begin_backporch(), sstvenc_encoder_begin_channel(), sstvenc_encoder_begin_frontporch(), sstvenc_encoder_begin_gap01(), sstvenc_encoder_begin_gap12(), sstvenc_encoder_begin_gap23(), and sstvenc_encoder_next_image_pulse().

Here is the caller graph for this function:

◆ sstvenc_encoder_next_seq_pulse()

static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_seq_pulse ( struct sstvenc_encoder *const enc)
static

Emit the next pulse in the pulse sequence. If there are no more pulses, call the call-back function (if defined).

Parameters
[in,out]encSSTV encoder instance
Returns
Next pulse in the sequence
Return values
NULLNo more pulses in the sequence.

Definition at line 426 of file sstv.c.

426 {
427 if (enc->seq && enc->seq->duration_ns) {
428 const struct sstvenc_encoder_pulse* pulse = enc->seq;
429 enc->seq++;
430#ifdef _DEBUG_SSTV
431 printf("%s: returning pulse at %p\n", __func__, (void*)pulse);
432#endif
433 return pulse;
434 } else if (enc->seq_done_cb) {
435#ifdef _DEBUG_SSTV
436 printf("%s: end of pulse sequence, calling callback\n",
437 __func__, (void*)(enc->seq_done_cb));
438#endif
439 sstvenc_encoder_callback* seq_done_cb = enc->seq_done_cb;
440 enc->seq_done_cb = NULL;
441 enc->seq = NULL;
442 seq_done_cb(enc);
443 } else {
444#ifdef _DEBUG_SSTV
445 printf("%s: end of pulse sequence, no callback\n", __func__);
446#endif
447 enc->seq_done_cb = NULL;
448 enc->seq = NULL;
449 }
450 return NULL;
451}
void sstvenc_encoder_callback(struct sstvenc_encoder *const enc)
Definition sstv.h:92

References sstvenc_encoder_pulse::duration_ns, sstvenc_encoder::seq, and sstvenc_encoder::seq_done_cb.

Referenced by sstvenc_encoder_next_image_pulse(), and sstvenc_encoder_next_pulse().

Here is the caller graph for this function:

◆ sstvenc_encoder_next_vis_pulse()

static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_vis_pulse ( struct sstvenc_encoder *const enc)
static

Determine and emit the next VIS header pulse to be sent.

Parameters
[in,out]encSSTV encoder instance
Returns
Pointer to SSTV VIS header pulse frequency (in Hz) and duration (in ns)
Return values
NULLEnd of VIS header.

Definition at line 488 of file sstv.c.

488 {
489 switch (enc->vars.vis.bit) {
491#ifdef _DEBUG_SSTV
492 printf("%s: VIS header start bit 1\n", __func__);
493#endif
496 enc->vars.vis.bit++;
497 return &(enc->pulse);
499#ifdef _DEBUG_SSTV
500 printf("%s: VIS header start bit 2\n", __func__);
501#endif
504 enc->vars.vis.bit++;
505 return &(enc->pulse);
507#ifdef _DEBUG_SSTV
508 printf("%s: VIS header start bit 3\n", __func__);
509#endif
512 enc->vars.vis.bit++;
513 return &(enc->pulse);
515#ifdef _DEBUG_SSTV
516 printf("%s: VIS header start bit 4\n", __func__);
517#endif
520 enc->vars.vis.bit++;
521 return &(enc->pulse);
529#ifdef _DEBUG_SSTV
530 printf("%s: VIS header data bit\n", __func__);
531#endif
534 enc->vars.vis.bit++;
535 return &(enc->pulse);
537#ifdef _DEBUG_SSTV
538 printf("%s: VIS header parity bit\n", __func__);
539#endif
542 enc->vars.vis.bit++;
543 return &(enc->pulse);
545#ifdef _DEBUG_SSTV
546 printf("%s: VIS header stop bit\n", __func__);
547#endif
550 enc->vars.vis.bit++;
551 return &(enc->pulse);
552 default:
553#ifdef _DEBUG_SSTV
554 printf("%s: VIS header is finished\n", __func__);
555#endif
556 /* This is the end of the VIS header */
557 return NULL;
558 }
559}
#define SSTVENC_VIS_BIT_DATA6
Definition sstv.c:72
#define SSTVENC_VIS_BIT_DATA4
Definition sstv.c:60
#define SSTVENC_VIS_BIT_DATA3
Definition sstv.c:54
#define SSTVENC_VIS_BIT_START4
Definition sstv.c:36
#define SSTVENC_VIS_BIT_START3
Definition sstv.c:33
#define SSTVENC_VIS_BIT_DATA7
Definition sstv.c:78
#define SSTVENC_VIS_BIT_DATA2
Definition sstv.c:48
#define SSTVENC_VIS_BIT_DATA1
Definition sstv.c:42
#define SSTVENC_VIS_BIT_PARITY
Definition sstv.c:84
#define SSTVENC_VIS_BIT_START2
Definition sstv.c:30
#define SSTVENC_VIS_BIT_DATA5
Definition sstv.c:66
#define SSTVENC_VIS_BIT_STOP
Definition sstv.c:89
static uint32_t sstvenc_encoder_vis_data_freq(struct sstvenc_encoder *const enc)
Definition sstv.c:462
static uint32_t sstvenc_encoder_vis_parity_freq(struct sstvenc_encoder *const enc)
Definition sstv.c:472
#define SSTVENC_FREQ_VIS_START
Definition sstvfreq.h:22
#define SSTVENC_FREQ_SYNC
Definition sstvfreq.h:19
#define SSTVENC_PERIOD_VIS_SYNC
Definition sstvmode.h:21
#define SSTVENC_PERIOD_VIS_BIT
Definition sstvmode.h:22
#define SSTVENC_PERIOD_VIS_START
Definition sstvmode.h:20

References sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data::bit, sstvenc_encoder_pulse::duration_ns, sstvenc_encoder_pulse::frequency, sstvenc_encoder::pulse, sstvenc_encoder_vis_data_freq(), sstvenc_encoder_vis_parity_freq(), SSTVENC_FREQ_SYNC, SSTVENC_FREQ_VIS_START, SSTVENC_PERIOD_VIS_BIT, SSTVENC_PERIOD_VIS_START, SSTVENC_PERIOD_VIS_SYNC, SSTVENC_VIS_BIT_DATA1, SSTVENC_VIS_BIT_DATA2, SSTVENC_VIS_BIT_DATA3, SSTVENC_VIS_BIT_DATA4, SSTVENC_VIS_BIT_DATA5, SSTVENC_VIS_BIT_DATA6, SSTVENC_VIS_BIT_DATA7, SSTVENC_VIS_BIT_PARITY, SSTVENC_VIS_BIT_START1, SSTVENC_VIS_BIT_START2, SSTVENC_VIS_BIT_START3, SSTVENC_VIS_BIT_START4, SSTVENC_VIS_BIT_STOP, sstvenc_encoder::vars, and sstvenc_encoder::sstvenc_encoder_phase_data::vis.

Referenced by sstvenc_encoder_next_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_on_finalseq_done()

static void sstvenc_encoder_on_finalseq_done ( struct sstvenc_encoder *const enc)
static

Handle the end of the end-of-image pulse sequence. This triggers a transition to sending the FSK ID.

Parameters
[in,out]encSSTV encoder instance

Definition at line 732 of file sstv.c.

732 {
733#ifdef _DEBUG_SSTV
734 printf("%s: end of final image sequence\n", __func__);
735#endif
737}
static void sstvenc_encoder_begin_fsk(struct sstvenc_encoder *const enc)
Definition sstv.c:976

References sstvenc_encoder_begin_fsk().

Referenced by sstvenc_encoder_next_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_on_initseq_done()

static void sstvenc_encoder_on_initseq_done ( struct sstvenc_encoder *const enc)
static

End of initialisation pulse sequence. This signals the beginning of the image scan.

Parameters
[in,out]encSSTV encoder instance

Definition at line 562 of file sstv.c.

562 {
563#ifdef _DEBUG_SSTV
564 printf("%s: initial sequence done\n", __func__);
565#endif
567}

References sstvenc_encoder_begin_image().

Referenced by sstvenc_encoder_next_pulse().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ sstvenc_encoder_vis_data_freq()

static uint32_t sstvenc_encoder_vis_data_freq ( struct sstvenc_encoder *const enc)
static

Compute the frequency for the next VIS data bit.

Parameters
[in,out]encSSTV encoder instance
Returns
SSTV VIS header data bit frequency in Hz.

Definition at line 462 of file sstv.c.

462 {
463 uint8_t bit = enc->vars.vis.bit - SSTVENC_VIS_BIT_DATA1;
464 if (enc->mode->vis_code & (1 << bit)) {
466 } else {
468 }
469}
#define SSTVENC_FREQ_VIS_BIT1
Definition sstvfreq.h:18
#define SSTVENC_FREQ_VIS_BIT0
Definition sstvfreq.h:20
uint8_t vis_code
Definition sstvmode.h:231

References sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data::bit, sstvenc_encoder::mode, SSTVENC_FREQ_VIS_BIT0, SSTVENC_FREQ_VIS_BIT1, SSTVENC_VIS_BIT_DATA1, sstvenc_encoder::vars, sstvenc_encoder::sstvenc_encoder_phase_data::vis, and sstvenc_mode::vis_code.

Referenced by sstvenc_encoder_next_vis_pulse().

Here is the caller graph for this function:

◆ sstvenc_encoder_vis_parity_freq()

static uint32_t sstvenc_encoder_vis_parity_freq ( struct sstvenc_encoder *const enc)
static

Compute the frequency for the VIS parity bit. The 8th bit of the VIS header is used to invert the parity for modes that require it.

Parameters
[in,out]encSSTV encoder instance
Returns
SSTV VIS header parity bit frequency in Hz.

Definition at line 472 of file sstv.c.

472 {
473 uint8_t ones = 0;
474 for (uint8_t i = 0; i < 8; i++) {
475 if (enc->mode->vis_code & (1 << i)) {
476 ones++;
477 }
478 }
479
480 if ((ones % 2) == 1) {
482 } else {
484 }
485}

References sstvenc_encoder::mode, SSTVENC_FREQ_VIS_BIT0, SSTVENC_FREQ_VIS_BIT1, and sstvenc_mode::vis_code.

Referenced by sstvenc_encoder_next_vis_pulse().

Here is the caller graph for this function:

Variable Documentation

◆ bit [1/2]

uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bit

The current bit of the byte being sent

Definition at line 173 of file sstv.h.

Referenced by sstvenc_encoder_begin_fsk(), sstvenc_encoder_fsk_load_next(), and sstvenc_encoder_next_fsk_pulse().

◆ bit [2/2]

uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data::bit

The current bit being sent

Definition at line 129 of file sstv.h.

Referenced by sstvenc_encoder_begin_vis(), sstvenc_encoder_next_vis_pulse(), and sstvenc_encoder_vis_data_freq().

◆ bv

uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::bv

The current byte value being sent

Definition at line 168 of file sstv.h.

Referenced by sstvenc_encoder_fsk_load_next(), and sstvenc_encoder_next_fsk_pulse().

◆ byte

uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::byte

The current byte position being sent

Definition at line 163 of file sstv.h.

Referenced by sstvenc_encoder_begin_fsk(), sstvenc_encoder_fsk_load_next(), and sstvenc_encoder_next_fsk_pulse().

◆ framebuffer

const uint8_t* sstvenc_encoder::framebuffer

The framebuffer holding the image to be sent. The image is assumed to be in the correct format for the SSTV mode, i.e. correct dimensions, channel count and colour space.

For colour SSTV modes, the values are interleaved for each channel, so c0, c1, c2; for the first pixel, then c0, c1, c2 for the second, etc. Use SSTVENC_MODE_GET_CH to determine what channel is what.

Definition at line 115 of file sstv.h.

Referenced by sstvenc_encoder_init(), and sstvenc_encoder_next_channel_pulse().

◆ fsk

◆ fsk_id

const char* sstvenc_encoder::fsk_id

The FSK-ID to be appended to the end. NULL for no FSK ID

Definition at line 103 of file sstv.h.

Referenced by sstvenc_encoder_begin_fsk(), sstvenc_encoder_fsk_load_next(), and sstvenc_encoder_init().

◆ mode

◆ phase

◆ pulse

struct sstvenc_encoder_pulse sstvenc_encoder::pulse

◆ scan

◆ seg_sz

uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::seg_sz

The current segment length

Definition at line 158 of file sstv.h.

Referenced by sstvenc_encoder_fsk_load_next().

◆ segment [1/2]

uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data::segment

The current byte segment being sent

Definition at line 153 of file sstv.h.

Referenced by sstvenc_encoder_begin_fsk(), sstvenc_encoder_fsk_load_next(), and sstvenc_encoder_next_fsk_pulse().

◆ segment [2/2]

uint8_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::segment

Scanline segment being emitted

Definition at line 146 of file sstv.h.

Referenced by sstvenc_encoder_next_image_pulse(), and sstvenc_encoder_next_scan_seg().

◆ seq

const struct sstvenc_encoder_pulse* sstvenc_encoder::seq

The current pulse sequence being emitted

Definition at line 118 of file sstv.h.

Referenced by sstvenc_encoder_begin_seq(), and sstvenc_encoder_next_seq_pulse().

◆ seq_done_cb

sstvenc_encoder_callback* sstvenc_encoder::seq_done_cb

What to do if the sequence is done?

Definition at line 121 of file sstv.h.

Referenced by sstvenc_encoder_begin_seq(), and sstvenc_encoder_next_seq_pulse().

◆ sstvenc_encoder_fsk_preamble

const uint8_t sstvenc_encoder_fsk_preamble[] = {0x20, 0x2a}
static

Definition at line 897 of file sstv.c.

897{0x20, 0x2a};

Referenced by sstvenc_encoder_fsk_load_next().

◆ sstvenc_encoder_fsk_tail

const uint8_t sstvenc_encoder_fsk_tail[] = {0x01}
static

Definition at line 898 of file sstv.c.

898{0x01};

Referenced by sstvenc_encoder_fsk_load_next().

◆ vars

◆ vis

◆ x

uint16_t sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data::x

The current image X position being scanned

Definition at line 136 of file sstv.h.

Referenced by sstvenc_encoder_begin_channel(), sstvenc_encoder_next_channel_pulse(), and sstvenc_encoder_next_image_pulse().

◆ y