2016-07-29 15:03:09 +00:00
|
|
|
//
|
|
|
|
// CommodoreGCR.cpp
|
|
|
|
// Clock Signal
|
|
|
|
//
|
|
|
|
// Created by Thomas Harte on 29/07/2016.
|
2018-05-13 19:19:52 +00:00
|
|
|
// Copyright 2016 Thomas Harte. All rights reserved.
|
2016-07-29 15:03:09 +00:00
|
|
|
//
|
|
|
|
|
|
|
|
#include "CommodoreGCR.hpp"
|
2016-09-14 01:53:36 +00:00
|
|
|
#include <limits>
|
2016-07-29 15:03:09 +00:00
|
|
|
|
|
|
|
using namespace Storage;
|
|
|
|
|
2017-03-26 18:34:47 +00:00
|
|
|
Time Storage::Encodings::CommodoreGCR::length_of_a_bit_in_time_zone(unsigned int time_zone) {
|
2016-07-29 15:03:09 +00:00
|
|
|
// the speed zone divides a 4Mhz clock by 13, 14, 15 or 16, with higher-numbered zones being faster (i.e. each bit taking less time)
|
2018-07-01 21:59:43 +00:00
|
|
|
return Time(16 - time_zone, 4000000u);
|
2016-07-29 15:03:09 +00:00
|
|
|
}
|
2016-08-01 10:04:55 +00:00
|
|
|
|
2017-03-26 18:34:47 +00:00
|
|
|
unsigned int Storage::Encodings::CommodoreGCR::encoding_for_nibble(uint8_t nibble) {
|
|
|
|
switch(nibble & 0xf) {
|
2016-09-14 01:53:36 +00:00
|
|
|
case 0x0: return 0x0a; case 0x1: return 0x0b;
|
|
|
|
case 0x2: return 0x12; case 0x3: return 0x13;
|
|
|
|
case 0x4: return 0x0e; case 0x5: return 0x0f;
|
|
|
|
case 0x6: return 0x16; case 0x7: return 0x17;
|
|
|
|
case 0x8: return 0x09; case 0x9: return 0x19;
|
|
|
|
case 0xa: return 0x1a; case 0xb: return 0x1b;
|
|
|
|
case 0xc: return 0x0d; case 0xd: return 0x1d;
|
|
|
|
case 0xe: return 0x1e; case 0xf: return 0x15;
|
2016-08-01 10:04:55 +00:00
|
|
|
|
|
|
|
// for the benefit of the compiler; clearly unreachable
|
|
|
|
default: return 0xff;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-26 18:34:47 +00:00
|
|
|
unsigned int Storage::Encodings::CommodoreGCR::decoding_from_quintet(unsigned int quintet) {
|
|
|
|
switch(quintet & 0x1f) {
|
2016-09-14 01:53:36 +00:00
|
|
|
case 0x0a: return 0x0; case 0x0b: return 0x1;
|
|
|
|
case 0x12: return 0x2; case 0x13: return 0x3;
|
|
|
|
case 0x0e: return 0x4; case 0x0f: return 0x5;
|
|
|
|
case 0x16: return 0x6; case 0x17: return 0x7;
|
|
|
|
case 0x09: return 0x8; case 0x19: return 0x9;
|
|
|
|
case 0x1a: return 0xa; case 0x1b: return 0xb;
|
|
|
|
case 0x0d: return 0xc; case 0x1d: return 0xd;
|
|
|
|
case 0x1e: return 0xe; case 0x15: return 0xf;
|
|
|
|
|
|
|
|
default: return std::numeric_limits<unsigned int>::max();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-26 18:34:47 +00:00
|
|
|
unsigned int Storage::Encodings::CommodoreGCR::encoding_for_byte(uint8_t byte) {
|
2016-08-01 10:04:55 +00:00
|
|
|
return encoding_for_nibble(byte) | (encoding_for_nibble(byte >> 4) << 5);
|
|
|
|
}
|
2016-08-01 12:41:16 +00:00
|
|
|
|
2017-03-26 18:34:47 +00:00
|
|
|
unsigned int Storage::Encodings::CommodoreGCR::decoding_from_dectet(unsigned int dectet) {
|
2016-09-14 01:53:36 +00:00
|
|
|
return decoding_from_quintet(dectet) | (decoding_from_quintet(dectet >> 5) << 4);
|
|
|
|
}
|
|
|
|
|
2017-03-26 18:34:47 +00:00
|
|
|
void Storage::Encodings::CommodoreGCR::encode_block(uint8_t *destination, uint8_t *source) {
|
2016-08-01 12:41:16 +00:00
|
|
|
unsigned int encoded_bytes[4] = {
|
|
|
|
encoding_for_byte(source[0]),
|
|
|
|
encoding_for_byte(source[1]),
|
|
|
|
encoding_for_byte(source[2]),
|
|
|
|
encoding_for_byte(source[3]),
|
|
|
|
};
|
|
|
|
|
2017-10-04 02:04:15 +00:00
|
|
|
destination[0] = static_cast<uint8_t>(encoded_bytes[0] >> 2);
|
|
|
|
destination[1] = static_cast<uint8_t>((encoded_bytes[0] << 6) | (encoded_bytes[1] >> 4));
|
|
|
|
destination[2] = static_cast<uint8_t>((encoded_bytes[1] << 4) | (encoded_bytes[2] >> 6));
|
|
|
|
destination[3] = static_cast<uint8_t>((encoded_bytes[2] << 2) | (encoded_bytes[3] >> 8));
|
|
|
|
destination[4] = static_cast<uint8_t>(encoded_bytes[3]);
|
2016-08-01 12:41:16 +00:00
|
|
|
}
|