Add a callsign field to the header - breaks backwards compatibility

This commit is contained in:
Philip Heron 2012-02-25 20:06:15 +00:00
parent 2df18c50a1
commit 3b87eca6bf
3 changed files with 95 additions and 32 deletions

14
main.c
View File

@ -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
View File

@ -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
View File

@ -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);