1 /*
2 * This file is part of libsidplayfp, a SID player engine.
3 *
4 * Copyright (C) 2014-2020 Leandro Nini
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include "UnitTest++/UnitTest++.h"
22 #include "UnitTest++/TestReporter.h"
23
24 #include "../src/builders/residfp-builder/residfp/Dac.cpp"
25
26 #define private public
27 #define protected public
28 #define class struct
29
30 #include "../src/builders/residfp-builder/residfp/EnvelopeGenerator.h"
31 #include "../src/builders/residfp-builder/residfp/EnvelopeGenerator.cpp"
32
33 using namespace UnitTest;
34
SUITE(EnvelopeGenerator)35 SUITE(EnvelopeGenerator)
36 {
37
38 struct TestFixture
39 {
40 // Test setup
41 TestFixture()
42 {
43 generator.reset();
44 generator.envelope_counter = 0;
45 }
46
47 reSIDfp::EnvelopeGenerator generator;
48 };
49
50 TEST_FIXTURE(TestFixture, TestADSRDelayBug)
51 {
52 // If the rate counter comparison value is set below the current value of the
53 // rate counter, the counter will continue counting up until it wraps around
54 // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the
55 // envelope can constly be stepped.
56
57 generator.writeATTACK_DECAY(0x70);
58
59 generator.writeCONTROL_REG(0x01);
60
61 // wait 200 cycles
62 for (int i=0; i<200; i++)
63 {
64 generator.clock();
65 }
66
67 CHECK_EQUAL(1, (int)generator.readENV());
68
69 // set lower Attack time
70 // should theoretically clock after 63 cycles
71 generator.writeATTACK_DECAY(0x20);
72
73 // wait another 200 cycles
74 for (int i=0; i<200; i++)
75 {
76 generator.clock();
77 }
78
79 CHECK_EQUAL(1, (int)generator.readENV());
80 }
81
82 TEST_FIXTURE(TestFixture, TestFlipFFto00)
83 {
84 // The envelope counter can flip from 0xff to 0x00 by changing state to
85 // release, then to attack. The envelope counter is then frozen at
86 // zero; to unlock this situation the state must be changed to release,
87 // then to attack.
88
89 generator.writeATTACK_DECAY(0x77);
90 generator.writeSUSTAIN_RELEASE(0x77);
91
92 generator.writeCONTROL_REG(0x01);
93
94 do
95 {
96 generator.clock();
97 } while ((int)generator.readENV() != 0xff);
98
99 generator.writeCONTROL_REG(0x00);
100 // run for three clocks, accounting for state pipeline
101 generator.clock();
102 generator.clock();
103 generator.clock();
104 generator.writeCONTROL_REG(0x01);
105
106 // wait at least 313 cycles
107 // so the counter is clocked once
108 for (int i=0; i<315; i++)
109 {
110 generator.clock();
111 }
112
113 CHECK_EQUAL(0, (int)generator.readENV());
114 }
115
116 TEST_FIXTURE(TestFixture, TestFlip00toFF)
117 {
118 // The envelope counter can flip from 0x00 to 0xff by changing state to
119 // attack, then to release. The envelope counter will then continue
120 // counting down in the release state.
121
122 generator.counter_enabled = false;
123
124 generator.writeATTACK_DECAY(0x77);
125 generator.writeSUSTAIN_RELEASE(0x77);
126 generator.clock();
127 CHECK_EQUAL(0, (int)generator.readENV());
128
129 generator.writeCONTROL_REG(0x01);
130 // run for three clocks, accounting for state pipeline
131 generator.clock();
132 generator.clock();
133 generator.clock();
134 generator.writeCONTROL_REG(0x00);
135
136 // wait at least 313 cycles
137 // so the counter is clocked once
138 for (int i=0; i<315; i++)
139 {
140 generator.clock();
141 }
142
143 CHECK_EQUAL(0xff, (int)generator.readENV());
144 }
145
146 }
147