Add a callsign field to the header - breaks backwards compatibility
This commit is contained in:
parent
2df18c50a1
commit
3b87eca6bf
14
main.c
14
main.c
|
@ -25,7 +25,7 @@
|
||||||
|
|
||||||
void exit_usage()
|
void exit_usage()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Usage: ssdv [-e|-d] [-t <percentage>] [-i <id>] [<in file>] [<out file>]\n");
|
fprintf(stderr, "Usage: ssdv [-e|-d] [-t <percentage>] [-c <callsign>] [-i <id>] [<in file>] [<out file>]\n");
|
||||||
exit(-1);
|
exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,19 +36,27 @@ int main(int argc, char *argv[])
|
||||||
FILE *fout = stdout;
|
FILE *fout = stdout;
|
||||||
char encode = -1;
|
char encode = -1;
|
||||||
int droptest = 0;
|
int droptest = 0;
|
||||||
|
char callsign[7];
|
||||||
uint8_t image_id = 0;
|
uint8_t image_id = 0;
|
||||||
ssdv_t ssdv;
|
ssdv_t ssdv;
|
||||||
|
|
||||||
uint8_t pkt[SSDV_PKT_SIZE], b[128], *jpeg;
|
uint8_t pkt[SSDV_PKT_SIZE], b[128], *jpeg;
|
||||||
size_t jpeg_length;
|
size_t jpeg_length;
|
||||||
|
|
||||||
|
callsign[0] = '\0';
|
||||||
|
|
||||||
opterr = 0;
|
opterr = 0;
|
||||||
while((c = getopt(argc, argv, "edi:t:")) != -1)
|
while((c = getopt(argc, argv, "edc:i:t:")) != -1)
|
||||||
{
|
{
|
||||||
switch(c)
|
switch(c)
|
||||||
{
|
{
|
||||||
case 'e': encode = 1; break;
|
case 'e': encode = 1; break;
|
||||||
case 'd': encode = 0; break;
|
case 'd': encode = 0; break;
|
||||||
|
case 'c':
|
||||||
|
if(strlen(optarg) > 6)
|
||||||
|
fprintf(stderr, "Warning: callsign is longer than 6 characters.\n");
|
||||||
|
strncpy(callsign, optarg, 6);
|
||||||
|
break;
|
||||||
case 'i': image_id = atoi(optarg); break;
|
case 'i': image_id = atoi(optarg); break;
|
||||||
case 't': droptest = atoi(optarg); break;
|
case 't': droptest = atoi(optarg); break;
|
||||||
case '?': exit_usage();
|
case '?': exit_usage();
|
||||||
|
@ -120,7 +128,7 @@ int main(int argc, char *argv[])
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /* Encode */
|
case 1: /* Encode */
|
||||||
ssdv_enc_init(&ssdv, image_id);
|
ssdv_enc_init(&ssdv, callsign, image_id);
|
||||||
ssdv_enc_set_buffer(&ssdv, pkt);
|
ssdv_enc_set_buffer(&ssdv, pkt);
|
||||||
|
|
||||||
i = 0;
|
i = 0;
|
||||||
|
|
107
ssdv.c
107
ssdv.c
|
@ -154,6 +154,50 @@ uint16_t crc_xmodem_update(uint16_t crc, uint8_t data)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static uint32_t encode_callsign(char *callsign)
|
||||||
|
{
|
||||||
|
uint32_t x;
|
||||||
|
char *c;
|
||||||
|
|
||||||
|
/* Point c at the end of the callsign */
|
||||||
|
for(c = callsign; *c; c++);
|
||||||
|
|
||||||
|
/* Encode it backwards */
|
||||||
|
x = 0;
|
||||||
|
for(c--; c >= callsign; c--)
|
||||||
|
{
|
||||||
|
x *= 40;
|
||||||
|
if(*c >= 'A' && *c <= 'Z') x += *c - 'A' + 14;
|
||||||
|
else if(*c >= 'a' && *c <= 'z') x += *c - 'a' + 14;
|
||||||
|
else if(*c >= '0' && *c <= '9') x += *c - '0' + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *decode_callsign(char *callsign, uint32_t code)
|
||||||
|
{
|
||||||
|
char *c, s;
|
||||||
|
|
||||||
|
*callsign = '\0';
|
||||||
|
|
||||||
|
/* Is callsign valid? */
|
||||||
|
if(code > 0xF423FFFF) return(0);
|
||||||
|
|
||||||
|
for(c = callsign; code; c++)
|
||||||
|
{
|
||||||
|
s = code % 40;
|
||||||
|
if(s == 0) *c = '-';
|
||||||
|
else if(s < 11) *c = '0' + s - 1;
|
||||||
|
else if(s < 14) *c = '-';
|
||||||
|
else *c = 'A' + s - 14;
|
||||||
|
code /= 40;
|
||||||
|
}
|
||||||
|
*c = '\0';
|
||||||
|
|
||||||
|
return(callsign);
|
||||||
|
}
|
||||||
|
|
||||||
static inline char jpeg_dht_lookup(ssdv_t *s, uint8_t *symbol, uint8_t *width)
|
static inline char jpeg_dht_lookup(ssdv_t *s, uint8_t *symbol, uint8_t *width)
|
||||||
{
|
{
|
||||||
uint16_t code = 0;
|
uint16_t code = 0;
|
||||||
|
@ -731,10 +775,11 @@ static char ssdv_have_marker_data(ssdv_t *s)
|
||||||
return(SSDV_OK);
|
return(SSDV_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
char ssdv_enc_init(ssdv_t *s, uint8_t image_id)
|
char ssdv_enc_init(ssdv_t *s, char *callsign, uint8_t image_id)
|
||||||
{
|
{
|
||||||
memset(s, 0, sizeof(ssdv_t));
|
memset(s, 0, sizeof(ssdv_t));
|
||||||
s->image_id = image_id;
|
s->image_id = image_id;
|
||||||
|
s->callsign = encode_callsign(callsign);
|
||||||
s->mode = S_ENCODING;
|
s->mode = S_ENCODING;
|
||||||
return(SSDV_OK);
|
return(SSDV_OK);
|
||||||
}
|
}
|
||||||
|
@ -848,16 +893,20 @@ char ssdv_enc_get_packet(ssdv_t *s)
|
||||||
/* A packet is ready, create the headers */
|
/* A packet is ready, create the headers */
|
||||||
s->out[0] = 0x55; /* Sync */
|
s->out[0] = 0x55; /* Sync */
|
||||||
s->out[1] = 0x66; /* Type */
|
s->out[1] = 0x66; /* Type */
|
||||||
s->out[2] = s->image_id; /* Image ID */
|
s->out[2] = s->callsign >> 24;
|
||||||
s->out[3] = s->packet_id >> 8; /* Packet ID MSB */
|
s->out[3] = s->callsign >> 16;
|
||||||
s->out[4] = s->packet_id & 0xFF; /* Packet ID LSB */
|
s->out[4] = s->callsign >> 8;
|
||||||
s->out[5] = s->width >> 4; /* Width / 16 */
|
s->out[5] = s->callsign;
|
||||||
s->out[6] = s->height >> 4; /* Height / 16 */
|
s->out[6] = s->image_id; /* Image ID */
|
||||||
s->out[7] = s->mcu_mode & 0x03; /* MCU mode (2 bits) */
|
s->out[7] = s->packet_id >> 8; /* Packet ID MSB */
|
||||||
s->out[8] = mcu_offset >> 8; /* Next MCU offset MSB */
|
s->out[8] = s->packet_id & 0xFF; /* Packet ID LSB */
|
||||||
s->out[9] = mcu_offset & 0xFF; /* Next MCU offset LSB */
|
s->out[9] = s->width >> 4; /* Width / 16 */
|
||||||
s->out[10] = mcu_id >> 8; /* MCU ID MSB */
|
s->out[10] = s->height >> 4; /* Height / 16 */
|
||||||
s->out[11] = mcu_id & 0xFF; /* MCU ID LSB */
|
s->out[11] = s->mcu_mode & 0x03; /* MCU mode (2 bits) */
|
||||||
|
s->out[12] = mcu_offset >> 8; /* Next MCU offset MSB */
|
||||||
|
s->out[13] = mcu_offset & 0xFF; /* Next MCU offset LSB */
|
||||||
|
s->out[14] = mcu_id >> 8; /* MCU ID MSB */
|
||||||
|
s->out[15] = mcu_id & 0xFF; /* MCU ID LSB */
|
||||||
|
|
||||||
/* Fill any remaining bytes with noise */
|
/* Fill any remaining bytes with noise */
|
||||||
if(s->out_len > 0) ssdv_memset_prng(s->outp, s->out_len);
|
if(s->out_len > 0) ssdv_memset_prng(s->outp, s->out_len);
|
||||||
|
@ -1025,9 +1074,9 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
|
||||||
uint16_t packet_id;
|
uint16_t packet_id;
|
||||||
|
|
||||||
/* Read the packet header */
|
/* Read the packet header */
|
||||||
packet_id = (packet[3] << 8) | packet[4];
|
packet_id = (packet[7] << 8) | packet[8];
|
||||||
s->packet_mcu_offset = (packet[8] << 8) | packet[9];
|
s->packet_mcu_offset = (packet[12] << 8) | packet[13];
|
||||||
s->packet_mcu_id = (packet[10] << 8) | packet[11];
|
s->packet_mcu_id = (packet[14] << 8) | packet[15];
|
||||||
|
|
||||||
if(s->packet_mcu_id != 0xFFFF) s->reset_mcu = s->packet_mcu_id;
|
if(s->packet_mcu_id != 0xFFFF) s->reset_mcu = s->packet_mcu_id;
|
||||||
|
|
||||||
|
@ -1035,13 +1084,15 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
|
||||||
if(s->packet_id == 0)
|
if(s->packet_id == 0)
|
||||||
{
|
{
|
||||||
const char *factor;
|
const char *factor;
|
||||||
|
char callsign[7];
|
||||||
|
|
||||||
/* Read the fixed headers from the packet */
|
/* Read the fixed headers from the packet */
|
||||||
s->image_id = packet[2];
|
s->callsign = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
|
||||||
s->width = packet[5] << 4;
|
s->image_id = packet[6];
|
||||||
s->height = packet[6] << 4;
|
s->width = packet[9] << 4;
|
||||||
s->mcu_count = packet[5] * packet[6];
|
s->height = packet[10] << 4;
|
||||||
s->mcu_mode = packet[7] & 0x03;
|
s->mcu_count = packet[9] * packet[10];
|
||||||
|
s->mcu_mode = packet[11] & 0x03;
|
||||||
|
|
||||||
switch(s->mcu_mode)
|
switch(s->mcu_mode)
|
||||||
{
|
{
|
||||||
|
@ -1052,6 +1103,7 @@ char ssdv_dec_feed(ssdv_t *s, uint8_t *packet)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Display information about the image */
|
/* Display information about the image */
|
||||||
|
fprintf(stderr, "Callsign: %s\n", decode_callsign(callsign, s->callsign));
|
||||||
fprintf(stderr, "Image ID: %02X\n", s->image_id);
|
fprintf(stderr, "Image ID: %02X\n", s->image_id);
|
||||||
fprintf(stderr, "Resolution: %ix%i\n", s->width, s->height);
|
fprintf(stderr, "Resolution: %ix%i\n", s->width, s->height);
|
||||||
fprintf(stderr, "MCU blocks: %i\n", s->mcu_count);
|
fprintf(stderr, "MCU blocks: %i\n", s->mcu_count);
|
||||||
|
@ -1195,14 +1247,15 @@ char ssdv_dec_is_packet(uint8_t *packet, int *errors)
|
||||||
|
|
||||||
void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet)
|
void ssdv_dec_header(ssdv_packet_info_t *info, uint8_t *packet)
|
||||||
{
|
{
|
||||||
info->image_id = packet[2];
|
info->callsign = (packet[2] << 24) | (packet[3] << 16) | (packet[4] << 8) | packet[5];
|
||||||
info->packet_id = (packet[3] << 8) | packet[4];
|
info->image_id = packet[6];
|
||||||
info->width = packet[5] << 4;
|
info->packet_id = (packet[7] << 8) | packet[8];
|
||||||
info->height = packet[6] << 4;
|
info->width = packet[9] << 4;
|
||||||
info->mcu_mode = packet[7] & 0x03;
|
info->height = packet[10] << 4;
|
||||||
info->mcu_offset = (packet[8] << 8) | packet[9];
|
info->mcu_mode = packet[11] & 0x03;
|
||||||
info->mcu_id = (packet[10] << 8) | packet[11];
|
info->mcu_offset = (packet[12] << 8) | packet[13];
|
||||||
info->mcu_count = packet[5] * packet[6];
|
info->mcu_id = (packet[14] << 8) | packet[15];
|
||||||
|
info->mcu_count = packet[9] * packet[10];
|
||||||
if(info->mcu_mode == 1 || info->mcu_mode == 2) info->mcu_count *= 2;
|
if(info->mcu_mode == 1 || info->mcu_mode == 2) info->mcu_count *= 2;
|
||||||
else if(info->mcu_mode == 3) info->mcu_count *= 4;
|
else if(info->mcu_mode == 3) info->mcu_count *= 4;
|
||||||
}
|
}
|
||||||
|
|
6
ssdv.h
6
ssdv.h
|
@ -33,7 +33,7 @@ extern "C" {
|
||||||
|
|
||||||
/* Packet details */
|
/* Packet details */
|
||||||
#define SSDV_PKT_SIZE (0x100)
|
#define SSDV_PKT_SIZE (0x100)
|
||||||
#define SSDV_PKT_SIZE_HEADER (0x0C)
|
#define SSDV_PKT_SIZE_HEADER (0x10)
|
||||||
#define SSDV_PKT_SIZE_CRC (0x02)
|
#define SSDV_PKT_SIZE_CRC (0x02)
|
||||||
#define SSDV_PKT_SIZE_RSCODES (0x20)
|
#define SSDV_PKT_SIZE_RSCODES (0x20)
|
||||||
#define SSDV_PKT_SIZE_PAYLOAD (SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_RSCODES)
|
#define SSDV_PKT_SIZE_PAYLOAD (SSDV_PKT_SIZE - SSDV_PKT_SIZE_HEADER - SSDV_PKT_SIZE_CRC - SSDV_PKT_SIZE_RSCODES)
|
||||||
|
@ -46,6 +46,7 @@ typedef struct
|
||||||
/* Image information */
|
/* Image information */
|
||||||
uint16_t width;
|
uint16_t width;
|
||||||
uint16_t height;
|
uint16_t height;
|
||||||
|
uint32_t callsign;
|
||||||
uint8_t image_id;
|
uint8_t image_id;
|
||||||
uint16_t packet_id;
|
uint16_t packet_id;
|
||||||
uint8_t mcu_mode; /* 0 = 2x2, 1 = 2x1, 2 = 1x2, 3 = 1x1 */
|
uint8_t mcu_mode; /* 0 = 2x2, 1 = 2x1, 2 = 1x2, 3 = 1x1 */
|
||||||
|
@ -108,6 +109,7 @@ typedef struct
|
||||||
} ssdv_t;
|
} ssdv_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint32_t callsign;
|
||||||
uint8_t image_id;
|
uint8_t image_id;
|
||||||
uint16_t packet_id;
|
uint16_t packet_id;
|
||||||
uint16_t width;
|
uint16_t width;
|
||||||
|
@ -119,7 +121,7 @@ typedef struct {
|
||||||
} ssdv_packet_info_t;
|
} ssdv_packet_info_t;
|
||||||
|
|
||||||
/* Encoding */
|
/* Encoding */
|
||||||
extern char ssdv_enc_init(ssdv_t *s, uint8_t image_id);
|
extern char ssdv_enc_init(ssdv_t *s, char *callsign, uint8_t image_id);
|
||||||
extern char ssdv_enc_set_buffer(ssdv_t *s, uint8_t *buffer);
|
extern char ssdv_enc_set_buffer(ssdv_t *s, uint8_t *buffer);
|
||||||
extern char ssdv_enc_get_packet(ssdv_t *s);
|
extern char ssdv_enc_get_packet(ssdv_t *s);
|
||||||
extern char ssdv_enc_feed(ssdv_t *s, uint8_t *buffer, size_t length);
|
extern char ssdv_enc_feed(ssdv_t *s, uint8_t *buffer, size_t length);
|
||||||
|
|
Loading…
Reference in New Issue