diff --git a/connection.go b/connection.go new file mode 100644 index 0000000..009024e --- /dev/null +++ b/connection.go @@ -0,0 +1,108 @@ +package main + +import ( + "github.com/gorilla/websocket" + "log" + "net/http" + "time" +) + +const ( + pongWait = 60 * time.Second + pingPeriod = (pongWait * 9) / 10 + maxMessageSize = 512 +) + +type connection struct { + // The i6502 machine + machine *Machine + + // Websocket connection + ws *websocket.Conn + + // Outgoing data channel + send chan []byte +} + +var ( + upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + } +) + +// Pump received websocket messages into the machine +func (c *connection) readPump() { + defer func() { + c.ws.Close() + }() + + c.ws.SetReadLimit(maxMessageSize) + c.ws.SetReadDeadline(time.Now().Add(pongWait)) + c.ws.SetPongHandler(func(string) error { c.ws.SetReadDeadline(time.Now().Add(pongWait)); return nil }) + for { + _, message, err := c.ws.ReadMessage() + if err != nil { + break + } + c.writeBytesToMachine(message) + } +} + +// Pump serial output from the machine into the socket +func (c *connection) writePump() { + ticker := time.NewTicker(pingPeriod) + + defer func() { + c.ws.Close() + }() + + for { + select { + case data, ok := <-c.machine.SerialTx: + if !ok { + c.write(websocket.CloseMessage, []byte{}) + return + } + if err := c.write(websocket.TextMessage, []byte{data}); err != nil { + return + } + case <-ticker.C: + if err := c.write(websocket.PingMessage, []byte{}); err != nil { + return + } + } + } +} + +func (c *connection) write(messageType int, payload []byte) error { + c.ws.SetWriteDeadline(time.Now().Add(10 * time.Second)) + return c.ws.WriteMessage(messageType, payload) +} + +func (c *connection) writeBytesToMachine(data []byte) { + for _, b := range data { + log.Printf("%c", b) + c.machine.SerialRx <- b + } +} + +func serveWs(w http.ResponseWriter, r *http.Request) { + if r.Method != "GET" { + http.Error(w, "Method not allowed", 405) + return + } + + ws, err := upgrader.Upgrade(w, r, nil) + if err != nil { + log.Println(err) + return + } + + c := &connection{machine: CreateMachine(), send: make(chan []byte, 256), ws: ws} + + go c.writePump() + + c.machine.Reset() + c.readPump() +} diff --git a/devices/acia6551.go b/devices/acia6551.go index e51a243..a52fcc0 100644 --- a/devices/acia6551.go +++ b/devices/acia6551.go @@ -30,12 +30,16 @@ type Acia6551 struct { rxFull bool txEmpty bool + rxInterruptEnabled bool + txInterruptEnabled bool + + InterruptChan chan bool + RxChan chan byte TxChan chan byte } -func NewAcia6551() *Acia6551 { - fmt.Println("Resetting the Acia6551") +func NewAcia6551(cpu *Cpu) *Acia6551 { acia := &Acia6551{} acia.Reset() return acia @@ -54,6 +58,11 @@ func (a *Acia6551) Reset() { a.lastTxWrite = 0 a.lastRxRead = 0 a.overrun = false + + a.rxInterruptEnabled = false + a.txInterruptEnabled = false + + a.InterruptChan = make(chan bool, 0) } func (a *Acia6551) Size() int { @@ -91,7 +100,9 @@ func (a *Acia6551) RxWrite(data byte) { a.rx = data a.rxFull = true - // TODO: IRQs + if a.rxInterruptEnabled { + // getbus.assertIrq() + } } func (a *Acia6551) statusRegister() byte { @@ -153,7 +164,6 @@ func (a *Acia6551) HasRx() bool { func (a *Acia6551) debugTxOutput() { if a.HasTx() { a.TxChan <- a.TxRead() - fmt.Printf("%c", a.TxRead()) } } diff --git a/home.html b/home.html new file mode 100644 index 0000000..0537907 --- /dev/null +++ b/home.html @@ -0,0 +1,99 @@ + + +
+