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