// license:BSD-3-Clause // copyright-holders:Krzysztof Strzecha /* .PTP Microkey Primo tape images */ #include #include "primoptp.h" #define PRIMO_WAVEENTRY_LOW -32768 #define PRIMO_WAVEENTRY_HIGH 32767 #define PRIMO_WAVEENTRY_ZERO 0 #define PRIMO_WAV_FREQUENCY 22050 #define PRIMO_BIT_1_PERIOD (312*2*0.000001) #define PRIMO_BIT_0_PERIOD (3*PRIMO_BIT_1_PERIOD) #define PRIMO_BIT_1_LENGTH (PRIMO_BIT_1_PERIOD*PRIMO_WAV_FREQUENCY) #define PRIMO_BIT_0_LENGTH (PRIMO_BIT_0_PERIOD*PRIMO_WAV_FREQUENCY) /* #define PRIMO_BIT_1_LENGTH 6 #define PRIMO_BIT_0_LENGTH 16 */ #define PRIMO_PAUSE_LENGTH 2000 #define PRIMO_FILE_PILOT_LENGTH ((4*PRIMO_BIT_1_LENGTH + 4*PRIMO_BIT_0_LENGTH)*512) #define PRIMO_BLOCK_PILOT_LENGTH ((8*PRIMO_BIT_1_LENGTH)*96 + (5*PRIMO_BIT_1_LENGTH + 3*PRIMO_BIT_0_LENGTH)*3) static uint32_t primo_tape_image_length; static int16_t *primo_emit_level(int16_t *p, int count, int level) { int i; for (i=0; i>(7-i)) & 0x01); return p; } static uint32_t primo_cassette_calculate_number_of_1(const uint8_t *bytes, uint16_t length) { int i,j; uint32_t number_of_1 = 0; for (i=0; i>j)&0x01) number_of_1++; return number_of_1; } static int primo_cassette_calculate_size_in_samples(const uint8_t *bytes, int length) { int i = 0, j = 0; uint8_t *b = (uint8_t*) bytes; uint32_t file_size = 0; uint16_t block_size = 0; uint32_t number_of_1 = 0; uint32_t number_of_0 = 0; uint32_t size_in_samples = 0; primo_tape_image_length = length; while (i < length) { size_in_samples += PRIMO_PAUSE_LENGTH; LOG_FORMATS ("Samples (pause): %u\n", size_in_samples); size_in_samples += PRIMO_FILE_PILOT_LENGTH; LOG_FORMATS ("Samples (file pilot): %u\n", size_in_samples); /* file size with header */ file_size = *(b+1) + *(b+2)*256; b += 3; LOG_FORMATS ("File size (with header): %u\n", file_size); /* b is now set on the first data byte of file it means first byte (type) of block */ j = 0; while (j < file_size-3) { size_in_samples += PRIMO_BLOCK_PILOT_LENGTH; LOG_FORMATS ("Samples (block pilot): %u\n", size_in_samples); /* block size without header but including CRC byte */ block_size = *(b+1) + *(b+2)*256; /* b is set on the first byte of block data */ b += 3; number_of_1 = primo_cassette_calculate_number_of_1(b, block_size); number_of_0 = (block_size)*8-number_of_1; size_in_samples += number_of_1 * PRIMO_BIT_1_LENGTH; size_in_samples += number_of_0 * PRIMO_BIT_0_LENGTH; LOG_FORMATS ("Samples (block data): %u\n", size_in_samples); LOG_FORMATS ("\tBlock size: %u\n", block_size); b += block_size; /* b is set on the first header byte of next block or file */ j += block_size+3; } i += file_size; } return size_in_samples; } static int primo_cassette_fill_wave(int16_t *buffer, int length, uint8_t *bytes) { int i = 0, j = 0, k; int16_t *p = buffer; uint8_t *b = bytes; uint32_t file_size = 0; uint16_t block_size = 0; LOG_FORMATS ("Image size: %d\n", length); while (i < primo_tape_image_length) { LOG_FORMATS ("Beginning Primo file\n"); /* pause */ p = primo_emit_level (p, PRIMO_PAUSE_LENGTH, PRIMO_WAVEENTRY_ZERO); LOG_FORMATS ("Samples (pause): %ld\n", (long int)(p-buffer)); /* file pilot */ for (k=0; k<512; k++) p = primo_output_byte (p, 0xaa); LOG_FORMATS ("Samples (file pilot): %ld\n", (long int)(p-buffer)); /* file size with header */ file_size = *(b+1) + *(b+2)*256; b += 3; LOG_FORMATS ("File size: %u\n", file_size); /* b is now set on the first data byte of file it means first byte (block type) of block header */ j = 0; while (j < file_size-3) { /* block pilot */ for (k=0; k<96; k++) p = primo_output_byte (p, 0xff); for (k=0; k<3; k++) p = primo_output_byte (p, 0xd3); LOG_FORMATS ("Samples (block pilot): %ld\n", (long int)(p-buffer)); /* block size without header but including CRC byte */ block_size = *(b+1) + *(b+2)*256; b += 3; for (k=0; k