libsstvenc
Asynchronous Analogue SSTV encoder
Loading...
Searching...
No Matches
sstv.c
Go to the documentation of this file.
1
7/*
8 * © Stuart Longland VK4MSL
9 * SPDX-License-Identifier: MIT
10 */
11
12#ifdef _DEBUG_SSTV
13#include <inttypes.h>
14#include <stdio.h>
15#endif
16
17#include <assert.h>
18#include <libsstvenc/sstv.h>
19#include <libsstvenc/sstvfreq.h>
20
27#define SSTVENC_VIS_BIT_START1 (0)
28
30#define SSTVENC_VIS_BIT_START2 (1)
31
33#define SSTVENC_VIS_BIT_START3 (2)
34
36#define SSTVENC_VIS_BIT_START4 (3)
37
42#define SSTVENC_VIS_BIT_DATA1 (4)
43
48#define SSTVENC_VIS_BIT_DATA2 (5)
49
54#define SSTVENC_VIS_BIT_DATA3 (6)
55
60#define SSTVENC_VIS_BIT_DATA4 (7)
61
66#define SSTVENC_VIS_BIT_DATA5 (8)
67
72#define SSTVENC_VIS_BIT_DATA6 (9)
73
78#define SSTVENC_VIS_BIT_DATA7 (10)
79
84#define SSTVENC_VIS_BIT_PARITY (11)
85
89#define SSTVENC_VIS_BIT_STOP (12)
90
94#define SSTVENC_VIS_BIT_END (13)
95
108#define SSTVENC_ENCODER_SCAN_SEGMENT_FRONTPORCH (0)
109
113#define SSTVENC_ENCODER_SCAN_SEGMENT_CH0 (1)
114
118#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP01 (2)
119
123#define SSTVENC_ENCODER_SCAN_SEGMENT_CH1 (3)
124
128#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP12 (4)
129
133#define SSTVENC_ENCODER_SCAN_SEGMENT_CH2 (5)
134
138#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP23 (6)
139
143#define SSTVENC_ENCODER_SCAN_SEGMENT_CH3 (7)
144
149#define SSTVENC_ENCODER_SCAN_SEGMENT_BACKPORCH (8)
150
154#define SSTVENC_ENCODER_SCAN_SEGMENT_NEXT (9)
164static void sstvenc_encoder_new_phase(struct sstvenc_encoder* const enc,
165 uint8_t phase);
166
174static void sstvenc_encoder_begin_seq(struct sstvenc_encoder* const enc,
175 const struct sstvenc_encoder_pulse* seq,
176 sstvenc_encoder_callback* on_done);
177
188static const struct sstvenc_encoder_pulse*
190
196static void sstvenc_encoder_begin_vis(struct sstvenc_encoder* const enc);
197
205static uint32_t
207
216static uint32_t
218
229static const struct sstvenc_encoder_pulse*
231
237static void sstvenc_encoder_begin_image(struct sstvenc_encoder* const enc);
238
244static void sstvenc_encoder_begin_scanline(struct sstvenc_encoder* const enc);
245
254static void sstvenc_encoder_begin_channel(struct sstvenc_encoder* const enc,
255 uint8_t segment, uint8_t ch);
256
265static void sstvenc_encoder_next_scan_seg(struct sstvenc_encoder* const enc,
266 uint8_t next_segment);
267
274static void
276
282static void sstvenc_encoder_begin_fsk(struct sstvenc_encoder* const enc);
283
290static void
292
299static void
301
308static void sstvenc_encoder_begin_gap01(struct sstvenc_encoder* const enc);
309
316static void sstvenc_encoder_begin_gap12(struct sstvenc_encoder* const enc);
317
324static void sstvenc_encoder_begin_gap23(struct sstvenc_encoder* const enc);
325
332static void
334
346static const struct sstvenc_encoder_pulse*
348 uint8_t ch);
349
360static const struct sstvenc_encoder_pulse*
362
369static void sstvenc_encoder_fsk_load_next(struct sstvenc_encoder* const enc);
370
381static const struct sstvenc_encoder_pulse*
383
384static void sstvenc_encoder_new_phase(struct sstvenc_encoder* const enc,
385 uint8_t phase) {
386#ifdef _DEBUG_SSTV
387 printf("%s: entering phase 0x%02x\n", __func__, phase);
388#endif
389 enc->phase = phase;
390}
391
393 const struct sstvenc_mode* mode, const char* fsk_id,
394 const uint8_t* framebuffer) {
395 memset(enc, 0, sizeof(struct sstvenc_encoder));
396 enc->mode = mode;
397 enc->fsk_id = fsk_id;
398 enc->framebuffer = framebuffer;
400}
401
402static void sstvenc_encoder_begin_seq(struct sstvenc_encoder* const enc,
403 const struct sstvenc_encoder_pulse* seq,
404 sstvenc_encoder_callback* on_done) {
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}
424
425static const struct sstvenc_encoder_pulse*
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}
452
453static void sstvenc_encoder_begin_vis(struct sstvenc_encoder* const enc) {
454#ifdef _DEBUG_SSTV
455 printf("%s: begin sending VIS header\n", __func__);
456#endif
459}
460
461static uint32_t
463 uint8_t bit = enc->vars.vis.bit - SSTVENC_VIS_BIT_DATA1;
464 if (enc->mode->vis_code & (1 << bit)) {
466 } else {
468 }
469}
470
471static uint32_t
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}
486
487static const struct sstvenc_encoder_pulse*
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}
560
561static void
563#ifdef _DEBUG_SSTV
564 printf("%s: initial sequence done\n", __func__);
565#endif
567}
568
569static void sstvenc_encoder_begin_image(struct sstvenc_encoder* const enc) {
570#ifdef _DEBUG_SSTV
571 printf("%s: begin image scan\n", __func__);
572#endif
574 enc->vars.scan.y = 0;
576}
577
578static void
580#ifdef _DEBUG_SSTV
581 printf("%s: begin row %u\n", __func__, enc->vars.scan.y);
582#endif
584}
585
586static void sstvenc_encoder_begin_channel(struct sstvenc_encoder* const enc,
587 uint8_t segment, uint8_t ch) {
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}
603
604static const struct sstvenc_encoder_pulse*
606 uint8_t ch) {
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}
675
676static void
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}
685
686static void sstvenc_encoder_begin_gap01(struct sstvenc_encoder* const enc) {
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}
694
695static void sstvenc_encoder_begin_gap12(struct sstvenc_encoder* const enc) {
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}
703
704static void sstvenc_encoder_begin_gap23(struct sstvenc_encoder* const enc) {
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}
712
713static void
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}
722
723static void sstvenc_encoder_next_scan_seg(struct sstvenc_encoder* const enc,
724 uint8_t next_segment) {
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}
730
731static void
733#ifdef _DEBUG_SSTV
734 printf("%s: end of final image sequence\n", __func__);
735#endif
737}
738
739static const struct sstvenc_encoder_pulse*
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}
891
892#define SSTVENC_ENCODER_FSK_SEGMENT_BEGIN (0)
893#define SSTVENC_ENCODER_FSK_SEGMENT_PREAMBLE (1)
894#define SSTVENC_ENCODER_FSK_SEGMENT_ID (2)
895#define SSTVENC_ENCODER_FSK_SEGMENT_TAIL (3)
896#define SSTVENC_ENCODER_FSK_SEGMENT_DONE (4)
897const static uint8_t sstvenc_encoder_fsk_preamble[] = {0x20, 0x2a};
898const static uint8_t sstvenc_encoder_fsk_tail[] = {0x01};
899
900static void sstvenc_encoder_fsk_load_next(struct sstvenc_encoder* const enc) {
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}
975
976static void sstvenc_encoder_begin_fsk(struct sstvenc_encoder* const enc) {
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}
994
995static const struct sstvenc_encoder_pulse*
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}
1030
1031const struct sstvenc_encoder_pulse*
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}
1107
#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
#define SSTVENC_ENCODER_PHASE_INIT
Definition sstv.h:57
#define SSTVENC_ENCODER_PHASE_FINALSEQ
Definition sstv.h:74
#define SSTVENC_ENCODER_PHASE_VIS
Definition sstv.h:60
#define SSTVENC_ENCODER_PHASE_INITSEQ
Definition sstv.h:63
#define SSTVENC_ENCODER_PHASE_DONE
Definition sstv.h:80
#define SSTVENC_ENCODER_PHASE_SCAN
Definition sstv.h:71
#define SSTVENC_ENCODER_PHASE_FSK
Definition sstv.h:77
#define SSTVENC_ENCODER_SCAN_SEGMENT_CH0
Definition sstv.c:113
#define SSTVENC_ENCODER_SCAN_SEGMENT_FRONTPORCH
Definition sstv.c:108
#define SSTVENC_ENCODER_SCAN_SEGMENT_BACKPORCH
Definition sstv.c:149
#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_GAP23
Definition sstv.c:138
#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP01
Definition sstv.c:118
#define SSTVENC_ENCODER_SCAN_SEGMENT_CH1
Definition sstv.c:123
#define SSTVENC_ENCODER_SCAN_SEGMENT_CH2
Definition sstv.c:133
#define SSTVENC_ENCODER_SCAN_SEGMENT_GAP12
Definition sstv.c:128
#define SSTVENC_VIS_BIT_START1
Definition sstv.c:27
#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
const uint8_t * framebuffer
Definition sstv.h:115
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
const struct sstvenc_mode * mode
Definition sstv.h:100
static void sstvenc_encoder_begin_gap23(struct sstvenc_encoder *const enc)
Definition sstv.c:704
static void sstvenc_encoder_begin_frontporch(struct sstvenc_encoder *const enc)
Definition sstv.c:677
static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_fsk_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:996
static const struct sstvenc_encoder_pulse * sstvenc_encoder_next_seq_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:426
static void sstvenc_encoder_on_initseq_done(struct sstvenc_encoder *const enc)
Definition sstv.c:562
static uint32_t sstvenc_encoder_vis_data_freq(struct sstvenc_encoder *const enc)
Definition sstv.c:462
const char * fsk_id
Definition sstv.h:103
static void sstvenc_encoder_on_finalseq_done(struct sstvenc_encoder *const enc)
Definition sstv.c:732
static uint32_t sstvenc_encoder_vis_parity_freq(struct sstvenc_encoder *const enc)
Definition sstv.c:472
#define SSTVENC_ENCODER_FSK_SEGMENT_PREAMBLE
Definition sstv.c:893
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_scan_data scan
#define SSTVENC_ENCODER_FSK_SEGMENT_TAIL
Definition sstv.c:895
static void sstvenc_encoder_begin_scanline(struct sstvenc_encoder *const enc)
Definition sstv.c:579
void sstvenc_encoder_callback(struct sstvenc_encoder *const enc)
Definition sstv.h:92
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_fsk_data fsk
struct sstvenc_encoder_pulse pulse
Definition sstv.h:124
sstvenc_encoder_callback * seq_done_cb
Definition sstv.h:121
#define SSTVENC_ENCODER_FSK_SEGMENT_BEGIN
Definition sstv.c:892
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_channel(struct sstvenc_encoder *const enc, uint8_t segment, uint8_t ch)
Definition sstv.c:586
void sstvenc_encoder_init(struct sstvenc_encoder *const enc, const struct sstvenc_mode *mode, const char *fsk_id, const uint8_t *framebuffer)
Definition sstv.c:392
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
const struct sstvenc_encoder_pulse * seq
Definition sstv.h:118
static void sstvenc_encoder_new_phase(struct sstvenc_encoder *const enc, uint8_t phase)
Definition sstv.c:384
static void sstvenc_encoder_begin_fsk(struct sstvenc_encoder *const enc)
Definition sstv.c:976
static void sstvenc_encoder_begin_vis(struct sstvenc_encoder *const enc)
Definition sstv.c:453
static void sstvenc_encoder_begin_gap01(struct sstvenc_encoder *const enc)
Definition sstv.c:686
static const uint8_t sstvenc_encoder_fsk_tail[]
Definition sstv.c:898
#define SSTVENC_ENCODER_FSK_SEGMENT_ID
Definition sstv.c:894
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_seq(struct sstvenc_encoder *const enc, const struct sstvenc_encoder_pulse *seq, sstvenc_encoder_callback *on_done)
Definition sstv.c:402
static const uint8_t sstvenc_encoder_fsk_preamble[]
Definition sstv.c:897
struct sstvenc_encoder::sstvenc_encoder_phase_data::sstvenc_encoder_phase_vis_data vis
uint8_t phase
Definition sstv.h:180
const struct sstvenc_encoder_pulse * sstvenc_encoder_next_pulse(struct sstvenc_encoder *const enc)
Definition sstv.c:1032
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
static void sstvenc_encoder_begin_image(struct sstvenc_encoder *const enc)
Definition sstv.c:569
union sstvenc_encoder::sstvenc_encoder_phase_data vars
#define SSTVENC_FREQ_VIS_BIT1
Definition sstvfreq.h:18
#define SSTVENC_FREQ_VIS_BIT0
Definition sstvfreq.h:20
uint16_t sstvenc_level_freq(uint8_t level)
Definition sstvfreq.c:13
#define SSTVENC_FREQ_FSKID_BIT1
Definition sstvfreq.h:25
#define SSTVENC_FREQ_VIS_START
Definition sstvfreq.h:22
#define SSTVENC_FREQ_SYNC
Definition sstvfreq.h:19
#define SSTVENC_FREQ_FSKID_BIT0
Definition sstvfreq.h:26
uint8_t vis_code
Definition sstvmode.h:231
const struct sstvenc_encoder_pulse * gap01
Definition sstvmode.h:179
const struct sstvenc_encoder_pulse * backporch
Definition sstvmode.h:198
uint16_t width
Definition sstvmode.h:215
const struct sstvenc_encoder_pulse * finalseq
Definition sstvmode.h:204
const struct sstvenc_encoder_pulse * gap23
Definition sstvmode.h:191
const struct sstvenc_encoder_pulse * gap12
Definition sstvmode.h:185
uint16_t colour_space_order
Definition sstvmode.h:226
const struct sstvenc_encoder_pulse * frontporch
Definition sstvmode.h:173
const struct sstvenc_encoder_pulse * initseq
Definition sstvmode.h:166
uint16_t height
Definition sstvmode.h:220
uint32_t scanline_period_ns[4]
Definition sstvmode.h:210
#define SSTVENC_PERIOD_FSKID_BIT
Definition sstvmode.h:24
#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
uint32_t sstvenc_get_pixel_posn(const struct sstvenc_mode *const mode, uint16_t x, uint16_t y)
Definition sstvmode.c:704