/******************************************************************* Generate samples for 1 byte ********************************************************************/ static inline int kc_cas_byte(int16_t *buffer, int sample_pos, uint8_t data) { int samples = 0; // write the byte for ( int i = 0; i < 8; i++ ) { if ( data & 0x01 ) { samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_BIT_1 ); } else { samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_BIT_0 ); } data >>= 1; } // byte separator samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_SEPARATOR); return samples; }
/******************************************************************* Generate samples for 1 byte ********************************************************************/ INLINE int kc_cas_byte(INT16 *buffer, int sample_pos, UINT8 data) { int samples = 0; // write the byte for ( int i = 0; i < 8; i++ ) { if ( data & 0x01 ) { samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_BIT_1 ); } else { samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_BIT_0 ); } data >>= 1; } // byte separator samples += kc_cas_cycle( buffer, sample_pos + samples, FREQ_SEPARATOR); return samples; }
static int kc_handle_cass(int16_t *buffer, const uint8_t *casdata, int type) { int data_pos = (type == KC_IMAGE_KCC || type == KC_IMAGE_KCM) ? 0 : 16; int sample_count = 0; int block_id = 1; // 1 sec of silence at start sample_count += kc_cas_silence(buffer, sample_count, KC_WAV_FREQUENCY); // 8000 cycles of BIT_1 for synchronization for (int i=0; i<8000; i++) sample_count += kc_cas_cycle( buffer, sample_count, FREQ_BIT_1); // on the entire file while( data_pos < kc_image_size ) { uint8_t checksum = 0; // 200 cycles of BIT_1 every block for (int i=0; i<200; i++) sample_count += kc_cas_cycle( buffer, sample_count, FREQ_BIT_1); // separator sample_count += kc_cas_cycle( buffer, sample_count, FREQ_SEPARATOR); // in TAP and TP2 file the first byte is the ID if (type == KC_IMAGE_TAP || type == KC_IMAGE_TP2 || type == KC_IMAGE_KCM) block_id = casdata[data_pos++]; // is the last block ? if (data_pos + 128 >= kc_image_size && type == KC_IMAGE_KCC) block_id = 0xff; // write the block ID sample_count += kc_cas_byte( buffer, sample_count, block_id ); // write the 128 bytes of the block for (int i=0; i<128; i++) { uint8_t data = 0; if (data_pos < kc_image_size) data = casdata[data_pos++]; // calculate the checksum checksum += data; // write a byte sample_count += kc_cas_byte( buffer, sample_count, data ); } // TP2 and KCM files also have the checksum byte if (type == KC_IMAGE_TP2 || type == KC_IMAGE_KCM) checksum = casdata[data_pos++]; // 8bit checksum sample_count += kc_cas_byte( buffer, sample_count, checksum ); // more TAP and TP2 can be combined into the same file if ((type == KC_IMAGE_TAP || type == KC_IMAGE_TP2) && block_id == 0xff && data_pos < kc_image_size) { if (casdata[data_pos] == 0xc3 || casdata[data_pos] == 0x4b) { sample_count += kc_cas_silence(buffer, sample_count, KC_WAV_FREQUENCY/10); data_pos += 16; } } block_id++; } sample_count += kc_cas_cycle( buffer, sample_count, FREQ_SEPARATOR); // 1 sec of silence sample_count += kc_cas_silence(buffer, sample_count, KC_WAV_FREQUENCY); return sample_count; }