xtPic.cpp (3936B)
1 #include "xtPic.h" 2 3 #include "xtLcd.h" 4 5 #include "mc68k/mc68k.h" 6 #include "mc68k/logging.h" 7 8 #include <cassert> 9 #include <cstdint> 10 11 namespace xt 12 { 13 Pic::Pic(mc68k::Mc68k& _uc, Lcd& _lcd) 14 { 15 _uc.getQSM().setSpiWriteCallback([&](const uint16_t _data, const uint8_t _index)->uint16_t 16 { 17 constexpr uint32_t transmitRamAddr = static_cast<uint32_t>(mc68k::PeriphAddress::TransmitRam0); 18 constexpr uint32_t receiveRamAddr = static_cast<uint32_t>(mc68k::PeriphAddress::ReceiveRam0); 19 constexpr uint32_t receiveRamSize = transmitRamAddr - receiveRamAddr; 20 static_assert(receiveRamSize == 32); 21 22 if(_index == 0) 23 { 24 // $30 enc 3 switches to multimode? 25 // $35 = Osc 1 Semitone 26 // $36 = Startwave1 27 // $37 = Mix Wave1 28 29 const uint8_t buttonA = m_spiButtons & 0x3f; 30 const uint8_t buttonB = (m_spiButtons>>1) & 0x20; 31 32 const uint16_t anus[] = 33 { 34 'M', // don't care 35 'W', // don't care 36 0x30, // encoder address for encoders 1-4, range 0x30 - 0x57 37 0, // encoder value 1 38 0, // encoder value 2 39 0, // encoder value 3 40 0, // encoder value 4 41 0x38, // encoder address for encoders 5-8, range 0x30 - 0x57 42 0, // encoder value 5 43 0, // encoder value 6 44 0, // encoder value 7 45 0, // encoder value 8 46 buttonA, // Button flags A 47 buttonB, // Button flags B 48 255, // main volume pot 49 'x' // We are an XT 50 }; 51 52 for(uint32_t a=0; a<std::size(anus); ++a) 53 _uc.write16(a*2 + receiveRamAddr, anus[a]); 54 } 55 56 if(_index == 0) 57 { 58 m_picCommand0 = _data; 59 return 0; 60 } 61 else if(_index == 1) 62 { 63 if(m_picCommand0 == 0x10) 64 { 65 if(_data == 0x80) 66 _lcd.resetWritePos(); 67 68 return 0; 69 } 70 } 71 72 // PIC Command 0x10 = new write, everything is for the LCD 73 // Pic Command 0x18 = continue to write and update LEDs too 74 75 assert(m_picCommand0 == 0x10 || m_picCommand0 == 0x18); 76 77 uint8_t lcdChar = m_picCommand0 == 0x10 ? static_cast<uint8_t>(_data) : 0; 78 79 if(m_picCommand0 == 0x18) 80 { 81 if(_index == 7) 82 m_picHasLedUpdate = _data == 0x14; 83 84 if(m_picHasLedUpdate) 85 { 86 switch (_index) 87 { 88 case 1: 89 case 2: 90 case 3: 91 case 4: 92 case 5: 93 case 6: 94 lcdChar = static_cast<uint8_t>(_data); 95 break; 96 case 8: 97 case 9: 98 case 10: 99 case 11: 100 { 101 const auto oldLedState = m_ledState; 102 m_ledState &= ~(0xff << ((_index-8) * 8)); 103 m_ledState |= (_data & 0xff) << ((_index-8) * 8); 104 if(oldLedState != m_ledState) 105 { 106 // MCLOG("LEDs: " << MCHEXN(m_ledState, 4)); 107 m_cbkLedsDirty(); 108 } 109 } 110 break; 111 default: 112 return 0; 113 } 114 } 115 else 116 { 117 lcdChar = static_cast<uint8_t>(_data); 118 } 119 } 120 if(lcdChar) 121 { 122 const auto ch = static_cast<char>(lcdChar); 123 124 if(_lcd.writeCharacter(ch)) 125 { 126 m_cbkLcdDirty(); 127 MCLOG("LCD:\n" << _lcd.toString()); 128 } 129 130 return 0; 131 } 132 return 0; 133 }); 134 } 135 136 Pic::~Pic() = default; 137 138 void Pic::setButton(const ButtonType _type, const bool _pressed) 139 { 140 const auto buttonMask = static_cast<uint8_t>(1 << static_cast<uint8_t>(_type)); 141 142 // inverted on purpose, pressed buttons are 0, released ones 1 143 if(_pressed) 144 m_spiButtons &= ~buttonMask; 145 else 146 m_spiButtons |= buttonMask; 147 } 148 149 bool Pic::getButton(ButtonType _button) const 150 { 151 const auto buttonMask = static_cast<uint8_t>(1 << static_cast<uint8_t>(_button)); 152 153 // inverted on purpose, pressed buttons are 0, released ones 1 154 return (m_spiButtons & buttonMask) == 0; 155 } 156 157 void Pic::setLcdDirtyCallback(const DirtyCallback& _cbk) 158 { 159 m_cbkLcdDirty = _cbk; 160 if(!m_cbkLcdDirty) 161 m_cbkLcdDirty = [] {}; 162 } 163 164 void Pic::setLedsDirtyCallback(const DirtyCallback& _cbk) 165 { 166 m_cbkLedsDirty = _cbk; 167 if(!m_cbkLedsDirty) 168 m_cbkLedsDirty = [] {}; 169 } 170 171 bool Pic::getLedState(const LedType _led) const 172 { 173 return m_ledState & (1 << _led); 174 } 175 }