1 module gbaid.comm; 2 3 import core.atomic : MemoryOrder, atomicLoad, atomicStore, atomicOp; 4 5 import gbaid.util; 6 7 import gbaid.gba.sio : Communication, CommunicationState; 8 9 public class SharedSerialData { 10 public shared uint[4] data; 11 /* 12 [0, 3] -> connected 13 [4, 7] -> ready 14 [8, 11] -> read 15 [12, 15] -> finalized 16 16 -> active 17 */ 18 public shared uint status; 19 20 this() { 21 data[] = 0xFFFFFFFF; 22 status = 0; 23 } 24 } 25 26 public class MappedMemoryCommunication : Communication { 27 private uint index; 28 private SharedSerialData _shared; 29 30 public this(uint index, SharedSerialData _shared) { 31 this.index = index; 32 this._shared = _shared; 33 34 atomicOp!"|="(_shared.status, 1 << index); 35 } 36 37 public ~this() { 38 atomicOp!"&="(_shared.status, ~(1 << index)); 39 atomicStore!(MemoryOrder.raw)(_shared.data[index], 0xFFFFFFFF); 40 } 41 42 public override CommunicationState getState() { 43 uint status = atomicLoad!(MemoryOrder.raw)(_shared.status); 44 45 uint connected = status.getBits(0, 3); 46 bool allRead = status.getBits(8, 11) == connected; 47 bool allFinalized = status.getBits(12, 15) == connected; 48 bool active = status.checkBit(16); 49 50 if (active && allRead && allFinalized) { 51 return CommunicationState.FINALIZE_DONE; 52 } 53 if (active && allRead) { 54 return CommunicationState.READ_DONE; 55 } 56 if (active) { 57 return CommunicationState.WRITE_DONE; 58 } 59 return CommunicationState.IDLE; 60 } 61 62 public override void setReady(uint index, bool ready) { 63 if (ready) { 64 atomicOp!"|="(_shared.status, 0b10000 << index); 65 } else { 66 atomicOp!"&="(_shared.status, ~(0b1000100010000 << index)); 67 atomicStore!(MemoryOrder.raw)(_shared.data[index], 0xFFFFFFFF); 68 } 69 } 70 71 public override bool allReady() { 72 uint status = atomicLoad!(MemoryOrder.raw)(_shared.status); 73 uint connected = status.getBits(0, 3); 74 return status.getBits(4, 7) == connected; 75 } 76 77 public override void init() { 78 atomicOp!"|="(_shared.status, 1 << 16); 79 } 80 81 public override void readDone(uint index, bool done) { 82 atomicOp!"|="(_shared.status, 1 << index + 8); 83 } 84 85 public override bool readDone(uint index) { 86 return atomicLoad!(MemoryOrder.raw)(_shared.status).checkBit(index + 8); 87 } 88 89 public override void finalizeDone(uint index, bool done) { 90 atomicOp!"|="(_shared.status, 1 << index + 12); 91 } 92 93 public override bool finalizeDone(uint index) { 94 return atomicLoad!(MemoryOrder.raw)(_shared.status).checkBit(index + 12); 95 } 96 97 public override void deinit() { 98 atomicOp!"&="(_shared.status, ~0b11111111100000000); 99 } 100 101 public override uint read(uint index) { 102 return atomicLoad!(MemoryOrder.raw)(_shared.data[index]); 103 } 104 105 public override void write(uint index, uint word) { 106 atomicStore!(MemoryOrder.raw)(_shared.data[index], word); 107 } 108 }