Skip to content

Commit 88b7ac6

Browse files
authored
Merge pull request #16 from saxbophone/josh/3-convert-bits-to-pits
Convert bits to pits
2 parents 8771e00 + e3a221a commit 88b7ac6

File tree

8 files changed

+303
-1
lines changed

8 files changed

+303
-1
lines changed

dengr/ChannelBit.hpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* @file
3+
*
4+
* @remarks This source file forms part of DENGR, a piece of software which
5+
* produces disc images which produce visible images on the recording side when
6+
* burned to Compact Disc.
7+
*
8+
* @author Joshua Saxby <[email protected]>
9+
* @date 2020
10+
*
11+
* @copyright Copyright (C) 2020 Joshua Saxby
12+
*
13+
* @copyright
14+
* This program is free software: you can redistribute it and/or modify
15+
* it under the terms of the GNU Affero General Public License as published
16+
* by the Free Software Foundation, either version 3 of the License, or
17+
* (at your option) any later version.
18+
*
19+
* @copyright
20+
* This program is distributed in the hope that it will be useful,
21+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
* GNU Affero General Public License for more details.
24+
*
25+
* @copyright
26+
* You should have received a copy of the GNU Affero General Public License
27+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
28+
*/
29+
#ifndef COM_SAXBOPHONE_DENGR_CHANNEL_BIT
30+
#define COM_SAXBOPHONE_DENGR_CHANNEL_BIT
31+
32+
#include <array>
33+
34+
35+
namespace com::saxbophone::dengr {
36+
/**
37+
* @brief Each Channel Frame comprises 588 Channel bits, these are those bits
38+
*/
39+
typedef bool ChannelBit;
40+
41+
/**
42+
* @brief Convenience typedef to allow making arrays of channel bits easier
43+
* @tparam LENGTH the length of the ChannelBitArray
44+
*/
45+
template<std::size_t LENGTH>
46+
using ChannelBitArray = std::array<ChannelBit, LENGTH>;
47+
}
48+
49+
#endif // include guard

dengr/Pit.hpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
#ifndef COM_SAXBOPHONE_DENGR_PIT
3030
#define COM_SAXBOPHONE_DENGR_PIT
3131

32+
#include <array>
33+
34+
3235
// TODO: Change to namespace com::saxbophone::dengr when move to C++20 complete
3336
namespace com::saxbophone::dengr {
3437
/**
@@ -43,6 +46,13 @@ namespace com::saxbophone::dengr {
4346
PIT = true, /**< A depression on the track's surface */
4447
LAND = false, /**< A flat area on the track's surface */
4548
};
49+
50+
/**
51+
* @brief Convenience typedef to allow making arrays of pits easier
52+
* @tparam LENGTH the length of the PitArray
53+
*/
54+
template<std::size_t LENGTH>
55+
using PitArray = std::array<Pit, LENGTH>;
4656
}
4757

4858
#endif // include guard

dengr/eight_to_fourteen.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
*/
2121
#include <array>
2222

23+
#include <cstddef>
24+
2325
// MSVC doesn't support the alternative operators out of the box
2426
#ifdef _MSC_VER
2527
#include <iso646.h>

dengr/physical_layer.hpp

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**
2+
* @file
3+
*
4+
* @remarks This source file forms part of DENGR, a piece of software which
5+
* produces disc images which produce visible images on the recording side when
6+
* burned to Compact Disc.
7+
*
8+
* @author Joshua Saxby <[email protected]>
9+
* @date 2020
10+
*
11+
* @copyright Copyright (C) 2020 Joshua Saxby
12+
*
13+
* @copyright
14+
* This program is free software: you can redistribute it and/or modify
15+
* it under the terms of the GNU Affero General Public License as published
16+
* by the Free Software Foundation, either version 3 of the License, or
17+
* (at your option) any later version.
18+
*
19+
* @copyright
20+
* This program is distributed in the hope that it will be useful,
21+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
* GNU Affero General Public License for more details.
24+
*
25+
* @copyright
26+
* You should have received a copy of the GNU Affero General Public License
27+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
28+
*/
29+
#ifndef COM_SAXBOPHONE_DENGR_PHYSICAL_LAYER
30+
#define COM_SAXBOPHONE_DENGR_PHYSICAL_LAYER
31+
32+
#include <array>
33+
34+
#include <cstddef>
35+
36+
#include "ChannelBit.hpp"
37+
#include "Pit.hpp"
38+
39+
40+
/**
41+
* @brief Functions for encoding sequences of bits to sequences of Pits/Lands
42+
* @details This implements the process described towards the end of ECMA-130,
43+
* sec 19.4
44+
*/
45+
namespace com::saxbophone::dengr::physical_layer {
46+
/**
47+
* @brief Encodes an array of Channel Bits into an equal-sized array of Pits
48+
* @details This uses Non-Return-to-Zero-Inverted (NRZI) encoding to encode
49+
* bits into pits.
50+
* @tparam LENGTH the length of the input and output arrays
51+
* @param previous_pit the value of the previous Pit seen immediately before
52+
* this upcoming array of Pits to be encoded
53+
* @param bits the array of Channel Bits to encode
54+
* @returns array of Pits representing the given input bits
55+
*/
56+
template<std::size_t LENGTH>
57+
PitArray<LENGTH> bits_to_pits(
58+
Pit previous_pit,
59+
ChannelBitArray<LENGTH> bits
60+
);
61+
62+
/**
63+
* @brief Decodes an array of Pits into an equal-sized array of Channel Bits
64+
* @details This uses Non-Return-to-Zero-Inverted (NRZI) encoding to decode
65+
* pits into bits
66+
* @tparam LENGTH the length of the input and output arrays
67+
* @param previous_pit the value of the previous Pit seen immediately before
68+
* this upcoming array of Pits to be decoded
69+
* @param pits the array of Pits to decode
70+
* @returns array of Channel Bits represented by the given input Pits
71+
*/
72+
template<std::size_t LENGTH>
73+
ChannelBitArray<LENGTH> pits_to_bits(
74+
Pit previous_pit,
75+
PitArray<LENGTH> pits
76+
);
77+
}
78+
79+
// because these functions are templated, their implementation follows immediately
80+
#include "physical_layer.inl"
81+
82+
#endif // include guard

dengr/physical_layer.inl

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/*
2+
* This source file forms part of DENGR, a piece of software which
3+
* produces disc images which produce visible images on the recording side when
4+
* burned to Compact Disc.
5+
*
6+
* Copyright (C) 2020 Joshua Saxby <[email protected]>
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Affero General Public License as published
10+
* by the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*/
21+
#include <utility>
22+
23+
#include <cstddef>
24+
25+
#include "ChannelBit.hpp"
26+
#include "Pit.hpp"
27+
28+
29+
namespace com::saxbophone::dengr::physical_layer {
30+
template<std::size_t LENGTH>
31+
PitArray<LENGTH> bits_to_pits(
32+
Pit previous_pit,
33+
ChannelBitArray<LENGTH> bits
34+
) {
35+
// used to keep track of what the current Pit/Land status is
36+
std::pair<Pit, Pit> state = { Pit::LAND, Pit::PIT, };
37+
// the first item is used as "current state", so swap if previous is PIT
38+
if (previous_pit == Pit::PIT) {
39+
std::swap(state.first, state.second);
40+
}
41+
PitArray<LENGTH> pits;
42+
for (std::size_t i = 0; i < LENGTH; i++) {
43+
// for each bit seen, if it's 1, swap states, otherwise, leave as-is
44+
if (bits[i] == 0b1) {
45+
std::swap(state.first, state.second);
46+
}
47+
// output the state in the first position of the pair
48+
pits[i] = state.first;
49+
}
50+
return pits;
51+
}
52+
53+
template<std::size_t LENGTH>
54+
ChannelBitArray<LENGTH> pits_to_bits(
55+
Pit previous_pit,
56+
PitArray<LENGTH> pits
57+
) {
58+
ChannelBitArray<LENGTH> bits = {};
59+
for (std::size_t i = 0; i < LENGTH; i++) {
60+
// as long as the pit is the same as previous, send 0
61+
if (pits[i] == previous_pit) {
62+
bits[i] = 0b0;
63+
} else {
64+
// otherwise, send 1 and update the "previous pit" to last-seen
65+
bits[i] = 0b1;
66+
previous_pit = pits[i];
67+
}
68+
}
69+
return bits;
70+
}
71+
}

dengr/scrambling.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
* along with this program. If not, see <https://www.gnu.org/licenses/>.
2020
*/
2121
#include <array>
22+
2223
#include <cstdint>
24+
#include <cstddef>
2325

2426
#include "Byte.hpp"
2527
#include "Mode2Sector.hpp"

tests/physical_layer.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
/*
2+
* This source file forms part of DENGR, a piece of software which
3+
* produces disc images which produce visible images on the recording side when
4+
* burned to Compact Disc.
5+
*
6+
* Copyright (C) 2020 Joshua Saxby <[email protected]>
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Affero General Public License as published
10+
* by the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Affero General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Affero General Public License
19+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
20+
*/
21+
#include <tuple>
22+
23+
#include <cstddef>
24+
25+
#include "../vendor/catch.hpp"
26+
27+
#include "../dengr/ChannelBit.hpp"
28+
#include "../dengr/Pit.hpp"
29+
#include "../dengr/physical_layer.hpp"
30+
31+
32+
using namespace com::saxbophone::dengr;
33+
using namespace com::saxbophone::dengr::physical_layer;
34+
35+
SCENARIO("Sequences of bits can be converted to/from sequences of pits/lands") {
36+
const std::size_t LENGTH = 8;
37+
// convenience typedef to keep the test case data lines within limits
38+
typedef std::tuple<Pit, std::uint8_t, std::uint8_t> TestData;
39+
// bits are stuffed into uints here for compactness
40+
auto bits_pits_combination = GENERATE(
41+
// previous-pit bits pits
42+
TestData(Pit::LAND, 0b01101001, 0b01001110),
43+
TestData(Pit::PIT , 0b01101001, 0b10110001),
44+
TestData(Pit::LAND, 0b11101010, 0b10110011),
45+
TestData(Pit::PIT , 0b00110011, 0b11011101),
46+
TestData(Pit::PIT , 0b00100100, 0b11000111),
47+
TestData(Pit::LAND, 0b00010000, 0b00011111),
48+
TestData(Pit::LAND, 0b11001101, 0b10001001),
49+
TestData(Pit::PIT , 0b11110111, 0b01011010),
50+
TestData(Pit::LAND, 0b10010010, 0b11100011),
51+
TestData(Pit::PIT , 0b00010010, 0b11100011),
52+
TestData(Pit::PIT , 0b10000000, 0b00000000),
53+
TestData(Pit::LAND, 0b00000000, 0b00000000)
54+
);
55+
// extract the bit patterns for use in the test case
56+
ChannelBitArray<LENGTH> bits;
57+
PitArray<LENGTH> pits;
58+
// also extract the previous pit value
59+
Pit previous_pit = std::get<0>(bits_pits_combination);
60+
for (std::uint8_t i = 0; i < 8; i++) {
61+
bits[i] = (std::get<1>(bits_pits_combination) & (1 << (7 - i))) != 0;
62+
pits[i] = (Pit)((std::get<2>(bits_pits_combination) & (1 << (7 - i))) != 0);
63+
}
64+
65+
GIVEN("A sequence of Channel Bits and its corresponding sequence of pits/lands") {
66+
WHEN("The bits are passed into the pit/land encoder") {
67+
PitArray<LENGTH> output = bits_to_pits(previous_pit, bits);
68+
THEN("The encoder should return a corresponding sequence of pits/lands") {
69+
// output should be equal to pits, which is what's expected
70+
REQUIRE(output == pits);
71+
}
72+
}
73+
}
74+
75+
GIVEN("A sequence of pits/lands and its corresponding sequence of Channel Bits") {
76+
WHEN("The pits/lands are passed into the pit/land decoder") {
77+
ChannelBitArray<LENGTH> output = pits_to_bits(previous_pit, pits);
78+
THEN("The decoder should return a corresponding sequence of bits") {
79+
// output should be equal to bits, which is what's expected
80+
REQUIRE(output == bits);
81+
}
82+
}
83+
}
84+
}

tests/scrambling.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
#include <iomanip>
2323
#include <sstream>
2424

25+
#include <cstddef>
26+
2527
#include "../vendor/catch.hpp"
2628

2729
#include "../dengr/Mode2Sector.hpp"
@@ -65,7 +67,7 @@ SCENARIO("Sectors can be scrambled according to ECMA-130 Annex B") {
6567
Mode2Sector raw_sector;
6668
ScrambledSector scrambled_sector;
6769
// try and read them both into the corresponding data structures
68-
for (size_t i = 0; i < 2352; i++) {
70+
for (std::size_t i = 0; i < 2352; i++) {
6971
// because C++ is a strict language, need a temporary to cast bytes
7072
char input_temp[1], output_temp[1];
7173
input_file.read(input_temp, 1);

0 commit comments

Comments
 (0)