n2xfrontpanel.cpp (6012B)
1 #include "n2xfrontpanel.h" 2 3 #include <cassert> 4 #include <cstring> // memcpy 5 6 #include "n2xhardware.h" 7 8 #include "dsp56kEmu/logging.h" 9 10 namespace n2x 11 { 12 template class FrontPanelCS<g_frontPanelAddressCS4>; 13 template class FrontPanelCS<g_frontPanelAddressCS6>; 14 15 template <uint32_t Base> FrontPanelCS<Base>::FrontPanelCS(FrontPanel& _fp): m_panel(_fp) 16 { 17 } 18 19 FrontPanelCS4::FrontPanelCS4(FrontPanel& _fp) : FrontPanelCS(_fp) 20 { 21 setKnobPosition(KnobType::PitchBend, 0); // pretend we're a rack unit 22 setKnobPosition(KnobType::ModWheel, 0); // pretend we're a rack unit 23 24 setKnobPosition(KnobType::MasterVol, 0xff); 25 setKnobPosition(KnobType::AmpGain, 0xff); 26 setKnobPosition(KnobType::Osc1Fm, 0); 27 setKnobPosition(KnobType::Porta, 0); 28 setKnobPosition(KnobType::Lfo2Rate, 0x0); 29 setKnobPosition(KnobType::Lfo1Rate, 0x0); 30 setKnobPosition(KnobType::ModEnvAmt, 0); 31 setKnobPosition(KnobType::ModEnvD, 0); 32 setKnobPosition(KnobType::ModEnvA, 0); 33 setKnobPosition(KnobType::AmpEnvD, 0); 34 setKnobPosition(KnobType::FilterFreq, 0xff); 35 setKnobPosition(KnobType::FilterEnvA, 0); 36 setKnobPosition(KnobType::AmpEnvA, 0); 37 setKnobPosition(KnobType::OscMix, 0x7f); 38 setKnobPosition(KnobType::Osc2Fine, 0x7f); 39 setKnobPosition(KnobType::Lfo1Amount, 0x0f); 40 setKnobPosition(KnobType::OscPW, 0x40); 41 setKnobPosition(KnobType::FilterEnvR, 0x30); 42 setKnobPosition(KnobType::AmpEnvR, 0x90); 43 setKnobPosition(KnobType::FilterEnvAmt, 0); 44 setKnobPosition(KnobType::FilterEnvS, 0x7f); 45 setKnobPosition(KnobType::AmpEnvS, 0x7f); 46 setKnobPosition(KnobType::FilterReso, 0x10); 47 setKnobPosition(KnobType::FilterEnvD, 0); 48 setKnobPosition(KnobType::ExpPedal, 0x0); 49 setKnobPosition(KnobType::Lfo2Amount, 0); 50 setKnobPosition(KnobType::Osc2Semi, 0x7f); 51 } 52 53 uint8_t FrontPanelCS4::read8(mc68k::PeriphAddress _addr) 54 { 55 const auto knobType = m_panel.cs6().getKnobType(); 56 57 if(knobType == KnobType::Invalid) 58 return 0; 59 60 return getKnobPosition(knobType); 61 } 62 63 uint8_t FrontPanelCS4::getKnobPosition(KnobType _knob) const 64 { 65 const auto i = static_cast<uint32_t>(_knob) - static_cast<uint32_t>(KnobType::First); 66 return m_knobPositions[i]; 67 } 68 69 void FrontPanelCS4::setKnobPosition(KnobType _knob, const uint8_t _value) 70 { 71 const auto i = static_cast<uint32_t>(_knob) - static_cast<uint32_t>(KnobType::First); 72 m_knobPositions[i] = _value; 73 } 74 75 FrontPanelCS6::FrontPanelCS6(FrontPanel& _fp) : FrontPanelCS(_fp), m_buttonStates({}) 76 { 77 m_buttonStates.fill(0xff); 78 } 79 80 void FrontPanelCS6::write8(const mc68k::PeriphAddress _addr, const uint8_t _val) 81 { 82 // LOG("Write CS6 " << HEXN(_addr - base(),2) << " = " << HEXN(_val,2)); 83 84 switch (static_cast<uint32_t>(_addr)) 85 { 86 case g_frontPanelAddressCS6 + 0x8: 87 m_ledLatch8 = _val; 88 break; 89 case g_frontPanelAddressCS6 + 0xa: 90 m_ledLatch10 = _val; 91 92 // LOG("Read pot " << HEXN((_val & 0x7f), 2)); 93 m_selectedKnob = static_cast<KnobType>(_val & 0x7f); 94 95 if(m_ledLatch10 & (1<<7)) 96 { 97 m_lcds[2] = m_ledLatch8; 98 onLCDChanged(); 99 } 100 break; 101 case g_frontPanelAddressCS6 + 0xc: 102 { 103 bool gotLCDs = false; 104 105 m_ledLatch12 = _val; 106 107 if(m_ledLatch12 & (1<<6)) 108 { 109 m_lcds[0] = m_ledLatch8; 110 gotLCDs = true; 111 } 112 if(m_ledLatch12 & (1<<7)) 113 { 114 m_lcds[1] = m_ledLatch8; 115 gotLCDs = true; 116 } 117 118 if(gotLCDs) 119 onLCDChanged(); 120 } 121 break; 122 } 123 FrontPanelCS::write8(_addr, _val); 124 } 125 126 uint8_t FrontPanelCS6::read8(mc68k::PeriphAddress _addr) 127 { 128 const auto a = static_cast<uint32_t>(_addr); 129 switch (a) 130 { 131 case g_frontPanelAddressCS6: return m_buttonStates[0]; 132 case g_frontPanelAddressCS6 + 2: return m_buttonStates[1]; 133 case g_frontPanelAddressCS6 + 4: return m_buttonStates[2]; 134 case g_frontPanelAddressCS6 + 6: return m_buttonStates[3]; 135 } 136 return FrontPanelCS::read8(_addr); 137 } 138 139 void FrontPanelCS6::setButtonState(ButtonType _button, const bool _pressed) 140 { 141 const auto id = static_cast<uint32_t>(_button); 142 const auto index = id>>9; 143 const auto mask = id & 0xff; 144 if(_pressed) 145 m_buttonStates[index] |= mask; 146 else 147 m_buttonStates[index] &= ~mask; 148 } 149 150 bool FrontPanelCS6::getButtonState(ButtonType _button) const 151 { 152 const auto id = static_cast<uint32_t>(_button); 153 const auto index = id>>9; 154 const auto mask = id & 0xff; 155 return m_buttonStates[index] & mask ? false : true; 156 } 157 158 void FrontPanelCS6::printLCD() const 159 { 160 static uint32_t count = 0; 161 ++count; 162 if(count & 0xff) 163 return; 164 /* 165 -- -- -- 166 | | | | | | 167 -- -- -- 168 | | | | | | 169 -- -- -- 170 */ 171 172 using Line = std::array<char, 16>; 173 std::array<Line,5> buf; 174 175 for (auto& b : buf) 176 { 177 b.fill(' '); 178 } 179 180 int off = 0; 181 182 auto drawH = [&](int _x, const int _y, const bool _set) 183 { 184 _x += off; 185 buf[_y][_x ] = _set ? '-' : ' '; 186 buf[_y][_x+1] = _set ? '-' : ' '; 187 }; 188 189 auto drawV = [&](int _x, const int _y, const bool _set) 190 { 191 _x += off; 192 buf[_y][_x] = _set ? '|' : ' '; 193 }; 194 195 for(auto i=0; i<3; ++i) 196 { 197 auto bt = [&](const uint32_t _bit) 198 { 199 return !(m_lcds[i] & (1<<_bit)); 200 }; 201 202 drawH(1, 0, bt(7)); 203 drawH(1, 2, bt(1)); 204 drawH(1, 4, bt(4)); 205 206 drawV(0, 1, bt(2)); 207 drawV(3, 1, bt(6)); 208 drawV(0, 3, bt(3)); 209 drawV(3, 3, bt(5)); 210 211 off += 6; 212 } 213 214 buf[4][4] = (m_lcds[0] & (1<<0)) ? ' ' : '*'; 215 216 char message[(sizeof(Line) + 1) * buf.size() + 1]; 217 size_t i=0; 218 for (const auto& line : buf) 219 { 220 memcpy(&message[i], line.data(), line.size()); 221 i += line.size(); 222 message[i++] = '\n'; 223 } 224 assert(i == std::size(message)-1); 225 message[i] = 0; 226 227 LOG("LCD:\n" << message); 228 } 229 230 void FrontPanelCS6::onLCDChanged() 231 { 232 // Check if the LCD displays " 1", used as indicator that device has finished booting 233 if(m_lcds[0] == 255 && m_lcds[1] >= 254 && m_lcds[2] == 159) 234 { 235 m_panel.getHardware().notifyBootFinished(); 236 } 237 #ifdef _DEBUG 238 printLCD(); 239 #endif 240 } 241 242 FrontPanel::FrontPanel(Hardware& _hardware) : m_hardware(_hardware), m_cs4(*this), m_cs6(*this) 243 { 244 } 245 }