1 #pragma once 2 3 #include <array> 4 #include <bitset> 5 #include <functional> 6 #include <mutex> 7 #include <utility> 8 #include "common_types.h" 9 10 namespace Teakra { 11 12 class ICU { 13 public: 14 using IrqBits = std::bitset<16>; GetRequest()15 u16 GetRequest() const { 16 std::lock_guard lock(mutex); 17 return (u16)request.to_ulong(); 18 } Acknowledge(u16 irq_bits)19 void Acknowledge(u16 irq_bits) { 20 std::lock_guard lock(mutex); 21 request &= ~IrqBits(irq_bits); 22 } GetAcknowledge()23 u16 GetAcknowledge() { 24 return 0; 25 } Trigger(u16 irq_bits)26 void Trigger(u16 irq_bits) { 27 std::lock_guard lock(mutex); 28 IrqBits bits(irq_bits); 29 request |= bits; 30 for (u32 irq = 0; irq < 16; ++irq) { 31 if (bits[irq]) { 32 for (u32 interrupt = 0; interrupt < enabled.size(); ++interrupt) { 33 if (enabled[interrupt][irq]) { 34 on_interrupt(interrupt); 35 } 36 } 37 if (vectored_enabled[irq]) { 38 on_vectored_interrupt(GetVector(irq), vector_context_switch[irq] != 0); 39 } 40 } 41 } 42 } GetTrigger()43 u16 GetTrigger() { 44 return 0; 45 } TriggerSingle(u32 irq)46 void TriggerSingle(u32 irq) { 47 Trigger(1 << irq); 48 } SetEnable(u32 interrupt_index,u16 irq_bits)49 void SetEnable(u32 interrupt_index, u16 irq_bits) { 50 std::lock_guard lock(mutex); 51 enabled[interrupt_index] = IrqBits(irq_bits); 52 } SetEnableVectored(u16 irq_bits)53 void SetEnableVectored(u16 irq_bits) { 54 std::lock_guard lock(mutex); 55 vectored_enabled = IrqBits(irq_bits); 56 } GetEnable(u32 interrupt_index)57 u16 GetEnable(u32 interrupt_index) const { 58 std::lock_guard lock(mutex); 59 return (u16)enabled[interrupt_index].to_ulong(); 60 } GetEnableVectored()61 u16 GetEnableVectored() const { 62 std::lock_guard lock(mutex); 63 return (u16)vectored_enabled.to_ulong(); 64 } 65 GetVector(u32 irq)66 u32 GetVector(u32 irq) const { 67 return vector_low[irq] | ((u32)vector_high[irq] << 16); 68 } 69 SetInterruptHandler(std::function<void (u32)> interrupt,std::function<void (u32,bool)> vectored_interrupt)70 void SetInterruptHandler(std::function<void(u32)> interrupt, 71 std::function<void(u32, bool)> vectored_interrupt) { 72 on_interrupt = std::move(interrupt); 73 on_vectored_interrupt = std::move(vectored_interrupt); 74 } 75 76 std::array<u16, 16> vector_low, vector_high; 77 std::array<u16, 16> vector_context_switch; 78 79 private: 80 std::function<void(u32)> on_interrupt; 81 std::function<void(u32, bool)> on_vectored_interrupt; 82 83 IrqBits request; 84 std::array<IrqBits, 3> enabled; 85 IrqBits vectored_enabled; 86 mutable std::mutex mutex; 87 }; 88 89 } // namespace Teakra 90