mirror of
https://github.com/romychs/Ocean-240.2-Emulator.git
synced 2026-04-21 11:03:21 +03:00
fdc mostly fixed
This commit is contained in:
parent
42fb80813c
commit
b133807f05
53
main.go
53
main.go
@ -1,6 +1,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
"fmt"
|
"fmt"
|
||||||
"image/color"
|
"image/color"
|
||||||
"okemu/config"
|
"okemu/config"
|
||||||
@ -19,6 +20,14 @@ import (
|
|||||||
var Version = "v1.0.0"
|
var Version = "v1.0.0"
|
||||||
var BuildTime = "2026-03-01"
|
var BuildTime = "2026-03-01"
|
||||||
|
|
||||||
|
//go:embed hex/format.hex
|
||||||
|
var serialBytes []byte
|
||||||
|
|
||||||
|
//go:embed bin/TYPE.COM
|
||||||
|
var ramBytes []byte
|
||||||
|
|
||||||
|
var needReset = false
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
fmt.Printf("Starting Ocean-240.2 emulator %s build at %s\n", Version, BuildTime)
|
fmt.Printf("Starting Ocean-240.2 emulator %s build at %s\n", Version, BuildTime)
|
||||||
@ -32,9 +41,19 @@ func main() {
|
|||||||
conf := config.GetConfig()
|
conf := config.GetConfig()
|
||||||
|
|
||||||
// Reconfigure logging by config values
|
// Reconfigure logging by config values
|
||||||
//logger.ReconfigureLogging(conf)
|
// logger.ReconfigureLogging(conf)
|
||||||
computer := okean240.New(conf)
|
|
||||||
|
|
||||||
|
computer := okean240.New(conf)
|
||||||
|
computer.SetSerialBytes(serialBytes)
|
||||||
|
|
||||||
|
w, raster, label := mainWindow(computer, conf)
|
||||||
|
|
||||||
|
go emulator(computer, raster, label, conf)
|
||||||
|
|
||||||
|
(*w).ShowAndRun()
|
||||||
|
}
|
||||||
|
|
||||||
|
func mainWindow(computer *okean240.ComputerType, emuConfig *config.OkEmuConfig) (*fyne.Window, *canvas.Raster, *widget.Label) {
|
||||||
emulatorApp := app.New()
|
emulatorApp := app.New()
|
||||||
w := emulatorApp.NewWindow("Океан 240.2")
|
w := emulatorApp.NewWindow("Океан 240.2")
|
||||||
w.Canvas().SetOnTypedKey(
|
w.Canvas().SetOnTypedKey(
|
||||||
@ -42,6 +61,11 @@ func main() {
|
|||||||
computer.PutKey(key)
|
computer.PutKey(key)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
w.Canvas().SetOnTypedRune(
|
||||||
|
func(key rune) {
|
||||||
|
computer.PutRune(key)
|
||||||
|
})
|
||||||
|
|
||||||
addShortcuts(w.Canvas(), computer)
|
addShortcuts(w.Canvas(), computer)
|
||||||
|
|
||||||
label := widget.NewLabel(fmt.Sprintf("Screen size: %dx%d", computer.ScreenWidth(), computer.ScreenHeight()))
|
label := widget.NewLabel(fmt.Sprintf("Screen size: %dx%d", computer.ScreenWidth(), computer.ScreenHeight()))
|
||||||
@ -61,9 +85,22 @@ func main() {
|
|||||||
widget.NewButton("Ctrl+C", func() {
|
widget.NewButton("Ctrl+C", func() {
|
||||||
computer.PutCtrlKey(0x03)
|
computer.PutCtrlKey(0x03)
|
||||||
}),
|
}),
|
||||||
|
widget.NewButton("Load Floppy", func() {
|
||||||
|
computer.LoadFloppy()
|
||||||
|
}),
|
||||||
|
widget.NewButton("Save Floppy", func() {
|
||||||
|
computer.SaveFloppy()
|
||||||
|
}),
|
||||||
|
widget.NewButton("RUN", func() {
|
||||||
|
computer.SetRamBytes(ramBytes)
|
||||||
|
}),
|
||||||
|
widget.NewButton("DUMP", func() {
|
||||||
|
computer.Dump(0x399, 15000)
|
||||||
|
}),
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
widget.NewButton("Reset", func() {
|
widget.NewButton("Reset", func() {
|
||||||
computer.Reset()
|
needReset = true
|
||||||
|
//computer.Reset(conf)
|
||||||
}),
|
}),
|
||||||
widget.NewSeparator(),
|
widget.NewSeparator(),
|
||||||
widget.NewButton("Закрыть", func() {
|
widget.NewButton("Закрыть", func() {
|
||||||
@ -78,12 +115,10 @@ func main() {
|
|||||||
|
|
||||||
w.SetContent(vBox)
|
w.SetContent(vBox)
|
||||||
|
|
||||||
go emulator(computer, raster, label)
|
return &w, raster, label
|
||||||
|
|
||||||
w.ShowAndRun()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label) {
|
func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *widget.Label, emuConfig *config.OkEmuConfig) {
|
||||||
ticker := time.NewTicker(133 * time.Nanosecond)
|
ticker := time.NewTicker(133 * time.Nanosecond)
|
||||||
var ticks = 0
|
var ticks = 0
|
||||||
var ticksCPU = 3
|
var ticksCPU = 3
|
||||||
@ -97,6 +132,10 @@ func emulator(computer *okean240.ComputerType, raster *canvas.Raster, label *wid
|
|||||||
nextSecond := time.Now().Add(time.Second).UnixMicro()
|
nextSecond := time.Now().Add(time.Second).UnixMicro()
|
||||||
curScrWidth := 256
|
curScrWidth := 256
|
||||||
for range ticker.C {
|
for range ticker.C {
|
||||||
|
if needReset {
|
||||||
|
computer.Reset(emuConfig)
|
||||||
|
needReset = false
|
||||||
|
}
|
||||||
ticks++
|
ticks++
|
||||||
if ticks%5 == 0 {
|
if ticks%5 == 0 {
|
||||||
// 1.5 MHz
|
// 1.5 MHz
|
||||||
|
|||||||
@ -1,12 +1,16 @@
|
|||||||
package okean240
|
package okean240
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
_ "embed"
|
||||||
|
"encoding/binary"
|
||||||
"image/color"
|
"image/color"
|
||||||
"okemu/config"
|
"okemu/config"
|
||||||
fdc2 "okemu/okean240/fdc"
|
fdc2 "okemu/okean240/fdc"
|
||||||
|
"okemu/okean240/pic"
|
||||||
"okemu/okean240/pit"
|
"okemu/okean240/pit"
|
||||||
"okemu/okean240/usart"
|
"okemu/okean240/usart"
|
||||||
"okemu/z80em"
|
"okemu/z80em"
|
||||||
|
"os"
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
@ -26,6 +30,7 @@ type ComputerType struct {
|
|||||||
bgColor byte
|
bgColor byte
|
||||||
dd70 *pit.I8253
|
dd70 *pit.I8253
|
||||||
dd72 *usart.I8251
|
dd72 *usart.I8251
|
||||||
|
dd75 *pic.I8259
|
||||||
fdc *fdc2.FloppyDriveController
|
fdc *fdc2.FloppyDriveController
|
||||||
kbdBuffer []byte
|
kbdBuffer []byte
|
||||||
vShift byte
|
vShift byte
|
||||||
@ -45,7 +50,11 @@ type ComputerInterface interface {
|
|||||||
Do() uint64
|
Do() uint64
|
||||||
TimerClk()
|
TimerClk()
|
||||||
PutKey(key *fyne.KeyEvent)
|
PutKey(key *fyne.KeyEvent)
|
||||||
|
PutRune(key rune)
|
||||||
PutCtrlKey(shortcut fyne.Shortcut)
|
PutCtrlKey(shortcut fyne.Shortcut)
|
||||||
|
SaveFloppy()
|
||||||
|
LoadFloppy()
|
||||||
|
Dump(start uint16, length uint16)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ComputerType) M1MemRead(addr uint16) byte {
|
func (c *ComputerType) M1MemRead(addr uint16) byte {
|
||||||
@ -81,25 +90,39 @@ func New(cfg *config.OkEmuConfig) *ComputerType {
|
|||||||
|
|
||||||
c.dd70 = pit.NewI8253()
|
c.dd70 = pit.NewI8253()
|
||||||
c.dd72 = usart.NewI8251()
|
c.dd72 = usart.NewI8251()
|
||||||
|
c.dd75 = pic.NewI8259()
|
||||||
c.fdc = fdc2.NewFDCType()
|
c.fdc = fdc2.NewFDCType()
|
||||||
|
|
||||||
return &c
|
return &c
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ComputerType) Reset() {
|
func (c *ComputerType) Reset(cfg *config.OkEmuConfig) {
|
||||||
c.cpu.Reset()
|
c.cpu.Reset()
|
||||||
c.cycles = 0
|
c.cycles = 0
|
||||||
c.vShift = 0
|
c.vShift = 0
|
||||||
c.hShift = 0
|
c.hShift = 0
|
||||||
|
|
||||||
|
c.memory = Memory{}
|
||||||
|
c.memory.Init(cfg.MonitorFile, cfg.CPMFile)
|
||||||
|
|
||||||
|
c.cycles = 0
|
||||||
|
c.dd17EnableOut = false
|
||||||
|
c.screenWidth = 512
|
||||||
|
c.screenHeight = 256
|
||||||
|
c.vRAM = c.memory.allMemory[3]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ComputerType) Do() int {
|
func (c *ComputerType) Do() int {
|
||||||
s := c.cpu.GetState()
|
//s := c.cpu.GetState()
|
||||||
if s.PC == 0xe0db {
|
//if s.PC == 0xe0db {
|
||||||
log.Debugf("breakpoint")
|
// log.Debugf("breakpoint")
|
||||||
}
|
//}
|
||||||
ticks := uint64(c.cpu.RunInstruction())
|
ticks := uint64(c.cpu.RunInstruction())
|
||||||
c.cycles += ticks
|
c.cycles += ticks
|
||||||
|
//if c.cpu.PC == 0x2C2 {
|
||||||
|
// log.Debugf("%4X: H:%X L:%X", c.cpu.PC, c.cpu.H, c.cpu.L)
|
||||||
|
//}
|
||||||
return int(ticks)
|
return int(ticks)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,15 +138,17 @@ func (c *ComputerType) GetPixel(x uint16, y uint16) color.RGBA {
|
|||||||
if x > 255 {
|
if x > 255 {
|
||||||
return CWhite
|
return CWhite
|
||||||
}
|
}
|
||||||
y += uint16(c.vShift)
|
|
||||||
x += uint16(c.hShift)
|
y += uint16(c.vShift) & 0x00ff
|
||||||
|
x += uint16(c.hShift) & 0x00ff
|
||||||
|
|
||||||
// Color 256x256 mode
|
// Color 256x256 mode
|
||||||
addr = ((x & 0xf8) << 6) | (y & 0xff)
|
addr = ((x & 0xf8) << 6) | (y & 0xff)
|
||||||
if c.vShift != 0 {
|
if c.vShift != 0 {
|
||||||
addr -= 8
|
addr -= 8
|
||||||
}
|
}
|
||||||
|
|
||||||
var cl byte = (c.vRAM.memory[addr&0x3fff] >> (x & 0x07)) & 1
|
cl := (c.vRAM.memory[addr&0x3fff] >> (x & 0x07)) & 1
|
||||||
cl |= (c.vRAM.memory[(addr+0x100)&0x3fff] >> (x & 0x07)) & 1 << 1
|
cl |= (c.vRAM.memory[(addr+0x100)&0x3fff] >> (x & 0x07)) & 1 << 1
|
||||||
if cl == 0 {
|
if cl == 0 {
|
||||||
resColor = BgColorPalette[c.bgColor]
|
resColor = BgColorPalette[c.bgColor]
|
||||||
@ -174,10 +199,61 @@ func (c *ComputerType) TimerClk() {
|
|||||||
|
|
||||||
// IRQ from timer
|
// IRQ from timer
|
||||||
if c.dd70.Fired(0) {
|
if c.dd70.Fired(0) {
|
||||||
c.ioPorts[PIC_DD75RS] |= Rst4TmrFlag
|
c.dd75.SetIRQ(RstTimerNo)
|
||||||
|
//c.ioPorts[PIC_DD75RS] |= Rst4Mask
|
||||||
}
|
}
|
||||||
// clock for SIO KR580VV51
|
// clock for SIO KR580VV51
|
||||||
if c.dd70.Fired(1) {
|
if c.dd70.Fired(1) {
|
||||||
c.dd72.Tick()
|
c.dd72.Tick()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) LoadFloppy() {
|
||||||
|
c.fdc.LoadFloppy()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) SaveFloppy() {
|
||||||
|
c.fdc.SaveFloppy()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) SetSerialBytes(bytes []byte) {
|
||||||
|
c.dd72.SetRxBytes(bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) SetRamBytes(bytes []byte) {
|
||||||
|
addr := 0x100
|
||||||
|
for i := 0; i < len(bytes); i++ {
|
||||||
|
c.memory.MemWrite(uint16(addr), bytes[i])
|
||||||
|
addr++
|
||||||
|
}
|
||||||
|
pages := len(bytes) / 256
|
||||||
|
if len(bytes)%256 != 0 {
|
||||||
|
pages++
|
||||||
|
}
|
||||||
|
log.Debugf("Loaded bytes: %d; blocks: %d", len(bytes), pages)
|
||||||
|
//c.cpu.SP = 0x100
|
||||||
|
//c.cpu.PC = 0x100
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) Dump(start uint16, length uint16) {
|
||||||
|
file, err := os.Create("dump.dat")
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(file *os.File) {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
}(file)
|
||||||
|
|
||||||
|
var buffer []byte
|
||||||
|
for addr := 0; addr < 65535; addr++ {
|
||||||
|
buffer = append(buffer, c.memory.MemRead(uint16(addr)))
|
||||||
|
}
|
||||||
|
err = binary.Write(file, binary.LittleEndian, buffer)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Save memory dump failed:", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -89,20 +89,23 @@ const TMR_DD70CTR = 0x63
|
|||||||
* Programmable Interrupt controller PIC KR580VV59
|
* Programmable Interrupt controller PIC KR580VV59
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// PIC_DD75RS RS Port
|
const RstKbdNo = 1
|
||||||
const PIC_DD75RS = 0x80
|
const RstTimerNo = 4
|
||||||
|
|
||||||
const Rst0SysFlag = 0x01 // System interrupt
|
const Rst0Mask = 0x01 // System interrupt
|
||||||
const Rst1KbdFlag = 0x02 // Keyboard interrupt
|
const Rst1Mask = 0x02 // Keyboard interrupt
|
||||||
const Rst2SerFlag = 0x04 // Serial interface interrupt
|
const Rst2Mask = 0x04 // Serial interface interrupt
|
||||||
const RstЗLptFlag = 0x08 // Printer ready
|
const RstЗMask = 0x08 // Printer ready
|
||||||
const Rst4TmrFlag = 0x10 // System timer
|
const Rst4Mask = 0x10
|
||||||
const Rst5PwrFlag = 0x20 // Power intRq
|
const Rst5Mask = 0x20 // Power intRq
|
||||||
const Rst6UsrFlag = 0x40 // User device 1 interrupt
|
const Rst6Mask = 0x40 // User device 1 interrupt
|
||||||
const Rst7UsrFlag = 0x80 // User device 1 interrupt
|
const Rst7Mask = 0x80 // User device 1 interrupt
|
||||||
|
|
||||||
// PIC_DD75RM RM Port
|
// PIC_DD75A Port A (a0=0)
|
||||||
const PIC_DD75RM = 0x81
|
const PIC_DD75A = 0x80
|
||||||
|
|
||||||
|
// PIC_DD75B Port B (a0=1)
|
||||||
|
const PIC_DD75B = 0x81
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* КР580ВВ51 DD72
|
* КР580ВВ51 DD72
|
||||||
|
|||||||
@ -1,48 +1,82 @@
|
|||||||
package fdc
|
package fdc
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Floppy drive controller, based on
|
* Floppy drive controller, based on
|
||||||
MB8877, К1818ВГ93
|
* MB8877, К1818ВГ93
|
||||||
|
*
|
||||||
By Romych, 2025.03.05
|
* By Romych, 2025.03.05
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
"os"
|
||||||
|
"slices"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
const FloppySizeK = 360
|
// Floppy parameters
|
||||||
|
const (
|
||||||
|
FloppySizeK = 720
|
||||||
|
SectorSize = 128
|
||||||
|
SideCount = 2
|
||||||
|
SectorPerTrack = 36
|
||||||
|
|
||||||
const SectorSize = 128
|
SizeInSectors = FloppySizeK * 1024 / SectorSize
|
||||||
const SideCount = 2
|
TracksCount = SizeInSectors / SideCount / SectorPerTrack
|
||||||
const SectorPerTrack = 36
|
SectorsPerSide = SizeInSectors / SideCount
|
||||||
|
|
||||||
const SizeInSectors = FloppySizeK * 1024 / SectorSize
|
TrackHeaderSize = 146
|
||||||
const TracksCount = SizeInSectors / SideCount / SectorPerTrack
|
TrackSectorSize = 626
|
||||||
const SectorsPerSide = SizeInSectors / SideCount
|
TrackFooterSize = 256 * 3
|
||||||
|
TrackBufferSize = TrackHeaderSize + TrackSectorSize*9 + TrackFooterSize
|
||||||
|
)
|
||||||
|
|
||||||
|
// FDC Commands
|
||||||
|
const (
|
||||||
|
CmdRestore byte = 0x0
|
||||||
|
CmdSeek byte = 0x1
|
||||||
|
CmdStep byte = 0x2
|
||||||
|
CmdStepIn byte = 0x5
|
||||||
|
CmdStepOut byte = 0x7
|
||||||
|
CmdReadSector byte = 0x8
|
||||||
|
CmdReadSectorMulti byte = 0x9
|
||||||
|
CmdWriteSector byte = 0xa
|
||||||
|
CmdWriteTrack byte = 0xf
|
||||||
|
CmdNoCommand byte = 0xff
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
StatusTR0 = 0x04 // TR0 - Head at track 0
|
||||||
|
StatusRNF = 0x10 // RNF - Record not found
|
||||||
|
StatusSeekError = 0x10 // Sector out of disk
|
||||||
|
StatusHeadLoaded = 0x20 // Head on disk
|
||||||
|
)
|
||||||
|
|
||||||
type SectorType []byte
|
type SectorType []byte
|
||||||
|
|
||||||
type FloppyDriveController struct {
|
type FloppyDriveController struct {
|
||||||
// Floppy controller port
|
// Floppy controller port
|
||||||
sideSel byte
|
sideNo byte
|
||||||
ddEn byte
|
ddEn byte
|
||||||
init byte
|
init byte
|
||||||
drSel byte
|
drive byte
|
||||||
mot1 byte
|
mot1 byte
|
||||||
mot0 byte
|
mot0 byte
|
||||||
intRq byte
|
intRq byte
|
||||||
motSt byte
|
motSt byte
|
||||||
sector byte
|
sectorNo byte
|
||||||
track byte
|
trackNo byte
|
||||||
drq byte
|
drq byte
|
||||||
// FloppyStorage
|
// FloppyStorage
|
||||||
sectors [SizeInSectors]SectorType
|
sectors [SizeInSectors]SectorType
|
||||||
data byte
|
data byte
|
||||||
status byte
|
status byte
|
||||||
lastCmd byte
|
lastCmd byte
|
||||||
curSector *SectorType
|
//curSector *SectorType
|
||||||
bytePtr uint16
|
bytePtr uint16
|
||||||
|
trackBuffer []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
type FloppyDriveControllerInterface interface {
|
type FloppyDriveControllerInterface interface {
|
||||||
@ -55,59 +89,96 @@ type FloppyDriveControllerInterface interface {
|
|||||||
SetData(value byte)
|
SetData(value byte)
|
||||||
Data() byte
|
Data() byte
|
||||||
Drq() byte
|
Drq() byte
|
||||||
|
SaveFloppy()
|
||||||
|
GetSectorNo() uint16
|
||||||
|
Track() byte
|
||||||
|
Sector() byte
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FloppyDriveController) GetSectorNo() uint16 {
|
||||||
|
return uint16(f.sideNo)*SectorsPerSide + uint16(f.trackNo)*SectorPerTrack + uint16(f.sectorNo) - 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FloppyDriveController) SetFloppy(val byte) {
|
func (f *FloppyDriveController) SetFloppy(val byte) {
|
||||||
// WR: 5-SSEN, 4-#DDEN, 3-INIT, 2-DRSEL, 1-MOT1, 0-MOT0
|
// WR: 5-SSEL, 4-#DDEN, 3-INIT, 2-DRSEL, 1-MOT1, 0-MOT0
|
||||||
f.sideSel = val >> 5 & 0x01
|
f.sideNo = val >> 5 & 0x01
|
||||||
f.ddEn = val >> 4 & 0x01
|
f.ddEn = val >> 4 & 0x01
|
||||||
f.init = val >> 3 & 0x01
|
f.init = val >> 3 & 0x01
|
||||||
f.drSel = val >> 2 & 0x01
|
f.drive = val >> 2 & 0x01
|
||||||
f.mot1 = val >> 1 & 0x01
|
f.mot1 = val >> 1 & 0x01
|
||||||
f.mot0 = val & 0x01
|
f.mot0 = val & 0x01
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FloppyDriveController) GetFloppy() byte {
|
func (f *FloppyDriveController) GetFloppy() byte {
|
||||||
// RD: 7-MOTST, 6-SSEL, 5,4-x , 3-DRSEL, 2-MOT1, 1-MOT0, 0-INT
|
// RD: 7-MOTST, 6-SSEL, 5,4-x , 3-DRSEL, 2-MOT1, 1-MOT0, 0-INT
|
||||||
floppy := f.intRq | (f.mot0 << 1) | (f.mot1 << 2) | (f.drSel << 3) | (f.sideSel << 6) | (f.motSt << 7)
|
floppy := f.intRq | (f.mot0 << 1) | (f.mot1 << 2) | (f.drive << 3) | (f.sideNo << 6) | (f.motSt << 7)
|
||||||
return floppy
|
return floppy
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
FdcCmdRestore byte = 0
|
|
||||||
FdcCmdSeek byte = 1
|
|
||||||
FdcCmdStep byte = 2
|
|
||||||
FdcCmdReadSector byte = 8
|
|
||||||
)
|
|
||||||
|
|
||||||
func (f *FloppyDriveController) SetCmd(value byte) {
|
func (f *FloppyDriveController) SetCmd(value byte) {
|
||||||
//log.Debugf("FCD CMD: %x", value)
|
|
||||||
f.lastCmd = value >> 4
|
f.lastCmd = value >> 4
|
||||||
switch f.lastCmd {
|
switch f.lastCmd {
|
||||||
case FdcCmdRestore:
|
case CmdRestore:
|
||||||
log.Debug("CMD Restore (seek track 0)")
|
log.Debug("CMD Restore (seek trackNo 0)")
|
||||||
f.status = 0x24 // TR0 & Head loaded
|
f.trackNo = 0
|
||||||
f.track = 0
|
f.status = StatusTR0 | StatusHeadLoaded // TR0 & Head loaded
|
||||||
case FdcCmdSeek:
|
case CmdSeek:
|
||||||
log.Debugf("CMD Seek %x", value&0xf)
|
log.Debugf("CMD Seek %x", value&0xf)
|
||||||
f.status = 0x04 // Head loaded
|
f.status = StatusHeadLoaded
|
||||||
f.track = f.data
|
f.trackNo = f.data
|
||||||
case FdcCmdStep:
|
case CmdStep:
|
||||||
log.Debugf("CMD Step %x", value&0xf)
|
log.Debugf("CMD Step %x", value&0xf)
|
||||||
f.status = 0x04 // Head loaded
|
f.status = StatusHeadLoaded
|
||||||
f.track = f.data
|
f.trackNo = f.data
|
||||||
case FdcCmdReadSector:
|
case CmdStepIn:
|
||||||
f.status = 0x04
|
log.Debugf("CMD StepIn (Next track) %x", value&0xf)
|
||||||
sectorNo := uint16(f.sideSel)*SectorsPerSide + uint16(f.track)*SectorPerTrack + uint16(f.sector)
|
f.status = StatusHeadLoaded
|
||||||
log.Debugf("CMD Read single sector: %d", sectorNo)
|
if f.trackNo < TracksCount {
|
||||||
if sectorNo >= SizeInSectors {
|
f.trackNo++
|
||||||
f.status = 0x10 // RNF - Record not found
|
}
|
||||||
} else {
|
case CmdStepOut:
|
||||||
f.curSector = &f.sectors[sectorNo]
|
log.Debugf("CMD StepOut (Previous track) %x", value&0xf)
|
||||||
f.bytePtr = 0
|
f.status = StatusHeadLoaded
|
||||||
|
if f.trackNo > 0 {
|
||||||
|
f.trackNo--
|
||||||
|
}
|
||||||
|
case CmdReadSector:
|
||||||
|
sectorNo := f.GetSectorNo()
|
||||||
|
log.Debugf("CMD Read single sectorNo: %d", sectorNo)
|
||||||
|
if sectorNo < SizeInSectors {
|
||||||
|
f.trackBuffer = slices.Clone(f.sectors[sectorNo])
|
||||||
f.drq = 1
|
f.drq = 1
|
||||||
f.status = 0x00
|
f.status = 0x00
|
||||||
|
} else {
|
||||||
|
f.drq = 0
|
||||||
|
f.status = StatusRNF
|
||||||
}
|
}
|
||||||
|
case CmdReadSectorMulti:
|
||||||
|
sectorNo := f.GetSectorNo()
|
||||||
|
f.trackBuffer = []byte{}
|
||||||
|
for c := 0; c < SectorPerTrack; c++ {
|
||||||
|
f.trackBuffer = slices.Concat(f.trackBuffer, f.sectors[sectorNo])
|
||||||
|
sectorNo++
|
||||||
|
}
|
||||||
|
f.drq = 1
|
||||||
|
f.status = 0x0
|
||||||
|
case CmdWriteSector:
|
||||||
|
sectorNo := f.GetSectorNo()
|
||||||
|
log.Debugf("CMD Write Sector %d", sectorNo)
|
||||||
|
if sectorNo < SizeInSectors {
|
||||||
|
f.bytePtr = 0
|
||||||
|
f.drq = 1
|
||||||
|
f.status = 0x0
|
||||||
|
f.trackBuffer = []byte{}
|
||||||
|
} else {
|
||||||
|
f.drq = 0
|
||||||
|
f.status = StatusRNF
|
||||||
|
}
|
||||||
|
case CmdWriteTrack:
|
||||||
|
log.Debugf("CMD Write Track %x", f.trackNo)
|
||||||
|
f.status = 0x00
|
||||||
|
f.trackBuffer = []byte{}
|
||||||
|
f.drq = 1
|
||||||
default:
|
default:
|
||||||
log.Debugf("Unknown CMD: %x VAL: %x", f.lastCmd, value&0xf)
|
log.Debugf("Unknown CMD: %x VAL: %x", f.lastCmd, value&0xf)
|
||||||
}
|
}
|
||||||
@ -117,31 +188,72 @@ func (f *FloppyDriveController) Status() byte {
|
|||||||
return f.status
|
return f.status
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FloppyDriveController) SetTrack(value byte) {
|
func (f *FloppyDriveController) SetTrackNo(value byte) {
|
||||||
log.Debugf("FCD Track: %d", value)
|
//log.Debugf("FDC Track: %d", value)
|
||||||
f.track = value
|
if value > TracksCount {
|
||||||
|
f.status |= 0x10 /// RNF
|
||||||
|
log.Error("Track not found!")
|
||||||
|
} else {
|
||||||
|
f.trackNo = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FloppyDriveController) SetSector(value byte) {
|
func (f *FloppyDriveController) SetSectorNo(value byte) {
|
||||||
log.Debugf("FCD Sector: %d", value)
|
//log.Debugf("FDC Sector: %d", value)
|
||||||
f.sector = value
|
if value > SectorPerTrack {
|
||||||
|
f.status |= 0x10
|
||||||
|
log.Error("Record not found!")
|
||||||
|
} else {
|
||||||
|
f.sectorNo = value
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FloppyDriveController) SetData(value byte) {
|
func (f *FloppyDriveController) SetData(value byte) {
|
||||||
log.Debugf("FCD Data: %d", value)
|
//log.Debugf("FCD Data: %d", value)
|
||||||
|
if f.lastCmd == CmdWriteTrack {
|
||||||
|
if len(f.trackBuffer) < TrackBufferSize {
|
||||||
|
f.trackBuffer = append(f.trackBuffer, value)
|
||||||
|
f.drq = 1
|
||||||
|
f.status = 0x00
|
||||||
|
} else {
|
||||||
|
//f.dump()
|
||||||
|
f.drq = 0
|
||||||
|
f.status = 0x00
|
||||||
|
f.lastCmd = CmdNoCommand
|
||||||
|
}
|
||||||
|
} else if f.lastCmd == CmdWriteSector {
|
||||||
|
if len(f.trackBuffer) < SectorSize {
|
||||||
|
f.trackBuffer = append(f.trackBuffer, value)
|
||||||
|
if len(f.trackBuffer) == SectorSize {
|
||||||
|
f.drq = 0
|
||||||
|
} else {
|
||||||
|
f.drq = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(f.trackBuffer) == SectorSize {
|
||||||
|
f.drq = 0
|
||||||
|
f.sectors[f.GetSectorNo()] = slices.Clone(f.trackBuffer)
|
||||||
|
f.lastCmd = CmdNoCommand
|
||||||
|
}
|
||||||
|
}
|
||||||
f.data = value
|
f.data = value
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *FloppyDriveController) Data() byte {
|
func (f *FloppyDriveController) Data() byte {
|
||||||
if f.lastCmd == FdcCmdReadSector {
|
switch f.lastCmd {
|
||||||
if f.bytePtr < SectorSize {
|
case CmdReadSector, CmdReadSectorMulti:
|
||||||
|
if len(f.trackBuffer) > 0 {
|
||||||
f.drq = 1
|
f.drq = 1
|
||||||
f.data = (*f.curSector)[f.bytePtr]
|
f.data = f.trackBuffer[0]
|
||||||
f.bytePtr++
|
f.trackBuffer = f.trackBuffer[1:]
|
||||||
} else {
|
}
|
||||||
|
if len(f.trackBuffer) == 0 {
|
||||||
f.drq = 0
|
f.drq = 0
|
||||||
f.status = 0
|
f.status = 0
|
||||||
|
f.lastCmd = CmdNoCommand
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
f.data = 0xff
|
||||||
}
|
}
|
||||||
return f.data
|
return f.data
|
||||||
}
|
}
|
||||||
@ -150,19 +262,78 @@ func (f *FloppyDriveController) Drq() byte {
|
|||||||
return f.drq
|
return f.drq
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FloppyDriveController) LoadFloppy() {
|
||||||
|
log.Debug("Load Floppy content.")
|
||||||
|
file, err := os.Open("floppy.okd")
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(file *os.File) {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
}(file)
|
||||||
|
|
||||||
|
for sector := 0; sector < SizeInSectors; sector++ {
|
||||||
|
var n int
|
||||||
|
n, err = file.Read(f.sectors[sector])
|
||||||
|
if n != SectorSize {
|
||||||
|
log.Error("Load floppy error, sector size: %d <> %d", n, SectorSize)
|
||||||
|
}
|
||||||
|
// err = binary.Read(file, binary.LittleEndian, f.sectors[sector])
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Load floppy content failed:", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FloppyDriveController) SaveFloppy() {
|
||||||
|
log.Debug("Save Floppy content.")
|
||||||
|
file, err := os.Create("floppy.okd")
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(file *os.File) {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
}(file)
|
||||||
|
|
||||||
|
// Write the struct to the file in little-endian byte order
|
||||||
|
for sector := 0; sector < SizeInSectors; sector++ {
|
||||||
|
var n int
|
||||||
|
n, err = file.Write(f.sectors[sector])
|
||||||
|
if n != SectorSize {
|
||||||
|
log.Errorf("Save floppy error, sector %d size: %d <> %d", sector, n, SectorSize)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Save floppy content failed:", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func NewFDCType() *FloppyDriveController {
|
func NewFDCType() *FloppyDriveController {
|
||||||
sec := [SizeInSectors]SectorType{}
|
sec := [SizeInSectors]SectorType{}
|
||||||
for i := 0; i < int(SizeInSectors); i++ {
|
for i := 0; i < SizeInSectors; i++ {
|
||||||
sec[i] = make([]byte, SectorSize)
|
sec[i] = make([]byte, SectorSize)
|
||||||
for s := 0; s < 128; s++ {
|
for s := 0; s < 128; s++ {
|
||||||
sec[i][s] = 0
|
sec[i][s] = 0xE5
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &FloppyDriveController{
|
return &FloppyDriveController{
|
||||||
sideSel: 0,
|
sideNo: 0,
|
||||||
ddEn: 0,
|
ddEn: 0,
|
||||||
init: 0,
|
init: 0,
|
||||||
drSel: 0,
|
drive: 0,
|
||||||
mot1: 0,
|
mot1: 0,
|
||||||
mot0: 0,
|
mot0: 0,
|
||||||
intRq: 0,
|
intRq: 0,
|
||||||
@ -174,4 +345,33 @@ func NewFDCType() *FloppyDriveController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *FloppyDriveController) dump() {
|
||||||
|
log.Debug("Dump Buffer content.")
|
||||||
|
file, err := os.Create("track-" + strconv.Itoa(int(f.trackNo)) + ".dat")
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer func(file *os.File) {
|
||||||
|
err := file.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Error(err)
|
||||||
|
}
|
||||||
|
}(file)
|
||||||
|
|
||||||
|
err = binary.Write(file, binary.LittleEndian, f.trackBuffer)
|
||||||
|
if err != nil {
|
||||||
|
log.Error("Save track content failed:", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FloppyDriveController) Track() byte {
|
||||||
|
return f.trackNo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FloppyDriveController) Sector() byte {
|
||||||
|
return f.sectorNo
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
@ -12,16 +12,14 @@ import log "github.com/sirupsen/logrus"
|
|||||||
|
|
||||||
func (c *ComputerType) IORead(port uint16) byte {
|
func (c *ComputerType) IORead(port uint16) byte {
|
||||||
switch port & 0x00ff {
|
switch port & 0x00ff {
|
||||||
case PIC_DD75RS:
|
case PIC_DD75A:
|
||||||
// PIO VN59
|
// PIO xx59, get IRR register
|
||||||
v := c.ioPorts[PIC_DD75RS]
|
return c.dd75.IRR()
|
||||||
c.ioPorts[PIC_DD75RS] = 0
|
|
||||||
return v
|
|
||||||
case UART_DD72RR:
|
case UART_DD72RR:
|
||||||
// SIO VV51 CMD
|
// USART VV51 CMD
|
||||||
return c.dd72.Status()
|
return c.dd72.Status()
|
||||||
case UART_DD72RD:
|
case UART_DD72RD:
|
||||||
// SIO VV51 Data
|
// USART VV51 Data
|
||||||
return c.dd72.Receive()
|
return c.dd72.Receive()
|
||||||
case KBD_DD78PA:
|
case KBD_DD78PA:
|
||||||
// Keyboard data
|
// Keyboard data
|
||||||
@ -36,6 +34,10 @@ func (c *ComputerType) IORead(port uint16) byte {
|
|||||||
return c.fdc.GetFloppy()
|
return c.fdc.GetFloppy()
|
||||||
case FDC_DATA:
|
case FDC_DATA:
|
||||||
return c.fdc.Data()
|
return c.fdc.Data()
|
||||||
|
case FDC_TRACK:
|
||||||
|
return c.fdc.Track()
|
||||||
|
case FDC_SECT:
|
||||||
|
return c.fdc.Sector()
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Debugf("IORead from port: %x", port)
|
log.Debugf("IORead from port: %x", port)
|
||||||
@ -89,23 +91,22 @@ func (c *ComputerType) IOWrite(port uint16, val byte) {
|
|||||||
c.dd70.Load(2, val)
|
c.dd70.Load(2, val)
|
||||||
|
|
||||||
case UART_DD72RR:
|
case UART_DD72RR:
|
||||||
// SIO VV51 CMD
|
// USART VV51 CMD
|
||||||
c.dd72.Command(val)
|
c.dd72.Command(val)
|
||||||
case UART_DD72RD:
|
case UART_DD72RD:
|
||||||
// SIO VV51 Data
|
// USART VV51 Data
|
||||||
c.dd72.Send(val)
|
c.dd72.Send(val)
|
||||||
case FDC_CMD:
|
case FDC_CMD:
|
||||||
c.fdc.SetCmd(val)
|
c.fdc.SetCmd(val)
|
||||||
case FDC_DATA:
|
case FDC_DATA:
|
||||||
c.fdc.SetData(val)
|
c.fdc.SetData(val)
|
||||||
case FDC_TRACK:
|
case FDC_TRACK:
|
||||||
c.fdc.SetTrack(val)
|
c.fdc.SetTrackNo(val)
|
||||||
case FDC_SECT:
|
case FDC_SECT:
|
||||||
c.fdc.SetSector(val)
|
c.fdc.SetSectorNo(val)
|
||||||
case FLOPPY:
|
case FLOPPY:
|
||||||
c.fdc.SetFloppy(val)
|
c.fdc.SetFloppy(val)
|
||||||
default:
|
default:
|
||||||
//log.Debugf("OUT to Unknown port (%x), %x", bp, val)
|
//log.Debugf("OUT to Unknown port (%x), %x", bp, val)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,51 +2,27 @@ package okean240
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fyne.io/fyne/v2"
|
"fyne.io/fyne/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (c *ComputerType) PutKey(key *fyne.KeyEvent) {
|
func (c *ComputerType) PutKey(key *fyne.KeyEvent) {
|
||||||
|
|
||||||
if key.Name == fyne.KeyUnknown {
|
code := RemapCmdKey[key.Name]
|
||||||
log.Debugf("Unknown key scancode: %X", key.Physical.ScanCode)
|
if code > 0 {
|
||||||
return
|
//log.Debugf("PutKey keyName: %s", key.Name)
|
||||||
}
|
|
||||||
|
|
||||||
log.Debugf("PutKey keyName: %s", key.Name)
|
|
||||||
|
|
||||||
if len(c.kbdBuffer) < KbdBufferSize {
|
|
||||||
|
|
||||||
var code byte
|
|
||||||
|
|
||||||
if (c.ioPorts[KBD_DD78PB] & 0x40) == 0 {
|
|
||||||
// No shift
|
|
||||||
code = RemapKey[key.Name]
|
|
||||||
} else {
|
|
||||||
// Shift
|
|
||||||
code = RemapKeyShift[key.Name]
|
|
||||||
}
|
|
||||||
c.ioPorts[KBD_DD78PB] &= 0x1f
|
|
||||||
|
|
||||||
if code != 0 {
|
|
||||||
c.ioPorts[KBD_DD78PA] = code
|
c.ioPorts[KBD_DD78PA] = code
|
||||||
c.ioPorts[PIC_DD75RS] |= Rst1KbdFlag
|
c.dd75.SetIRQ(RstKbdNo)
|
||||||
} else {
|
|
||||||
switch key.Name {
|
|
||||||
case "LeftAlt", "RightAlt":
|
|
||||||
c.ioPorts[KBD_DD78PB] |= 0x80
|
|
||||||
case "LeftControl", "RightControl":
|
|
||||||
c.ioPorts[KBD_DD78PB] |= 0x20
|
|
||||||
case "LeftShift", "RightShift":
|
|
||||||
log.Debug("Shift")
|
|
||||||
c.ioPorts[KBD_DD78PB] |= 0x40
|
|
||||||
default:
|
|
||||||
log.Debugf("Unhandled KeyName: %s code: %X", key.Name, key.Physical.ScanCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *ComputerType) PutRune(key rune) {
|
||||||
|
|
||||||
|
//log.Debugf("Put Rune: %c Lo: %x, Hi: %x", key, key&0xff, key>>8)
|
||||||
|
|
||||||
|
c.ioPorts[KBD_DD78PA] = byte(key & 0xff)
|
||||||
|
c.dd75.SetIRQ(RstKbdNo)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
CTRL_C EQU 0x03 ; Warm boot
|
CTRL_C EQU 0x03 ; Warm boot
|
||||||
CTRL_H EQU 0x08 ; Backspace
|
CTRL_H EQU 0x08 ; Backspace
|
||||||
@ -62,6 +38,7 @@ func (c *ComputerType) PutKey(key *fyne.KeyEvent) {
|
|||||||
|
|
||||||
func (c *ComputerType) PutCtrlKey(key byte) {
|
func (c *ComputerType) PutCtrlKey(key byte) {
|
||||||
c.ioPorts[KBD_DD78PA] = key
|
c.ioPorts[KBD_DD78PA] = key
|
||||||
c.ioPorts[PIC_DD75RS] |= Rst1KbdFlag
|
c.dd75.SetIRQ(RstKbdNo)
|
||||||
|
//c.ioPorts[PIC_DD75RS] |= Rst1Mask
|
||||||
c.ioPorts[KBD_DD78PB] &= 0x1f | 0x20
|
c.ioPorts[KBD_DD78PB] &= 0x1f | 0x20
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,7 +38,7 @@ var ColorPalette = [8][4]color.RGBA{
|
|||||||
|
|
||||||
// BgColorPalette Background color palette
|
// BgColorPalette Background color palette
|
||||||
var BgColorPalette = [8]color.RGBA{
|
var BgColorPalette = [8]color.RGBA{
|
||||||
CBlack, CBlue, CGreen, CLBlue, CRed, CCrimson, CYellow, CWhite,
|
CBlack, CBlue, CGreen, CLBlue, CRed, CCrimson /*CYellow*/, CBlack, CWhite,
|
||||||
}
|
}
|
||||||
|
|
||||||
//var MonoPalette = [8]color.RGBA{
|
//var MonoPalette = [8]color.RGBA{
|
||||||
|
|||||||
@ -2,6 +2,37 @@ package okean240
|
|||||||
|
|
||||||
import "fyne.io/fyne/v2"
|
import "fyne.io/fyne/v2"
|
||||||
|
|
||||||
|
var RemapCmdKey = map[fyne.KeyName]byte{
|
||||||
|
fyne.KeyEscape: 0x1B,
|
||||||
|
fyne.KeyReturn: 0x0A,
|
||||||
|
fyne.KeyTab: 0x09,
|
||||||
|
fyne.KeyBackspace: 0x08,
|
||||||
|
fyne.KeyInsert: 0x00,
|
||||||
|
fyne.KeyDelete: 0x08,
|
||||||
|
fyne.KeyRight: 0x18,
|
||||||
|
fyne.KeyLeft: 0x08,
|
||||||
|
fyne.KeyDown: 0x0A,
|
||||||
|
fyne.KeyUp: 0x19,
|
||||||
|
fyne.KeyPageUp: 0x00,
|
||||||
|
fyne.KeyPageDown: 0x00,
|
||||||
|
fyne.KeyHome: 0x0C,
|
||||||
|
fyne.KeyEnd: 0x1A,
|
||||||
|
fyne.KeyF1: 0x00,
|
||||||
|
fyne.KeyF2: 0x00,
|
||||||
|
fyne.KeyF3: 0x00,
|
||||||
|
fyne.KeyF4: 0x00,
|
||||||
|
fyne.KeyF5: 0x00,
|
||||||
|
fyne.KeyF6: 0x00,
|
||||||
|
fyne.KeyF7: 0x00,
|
||||||
|
fyne.KeyF8: 0x00,
|
||||||
|
fyne.KeyF9: 0x00,
|
||||||
|
fyne.KeyF10: 0x00,
|
||||||
|
fyne.KeyF11: 0x00,
|
||||||
|
fyne.KeyF12: 0x00,
|
||||||
|
fyne.KeyEnter: 0x0D,
|
||||||
|
fyne.KeyUnknown: 0x00,
|
||||||
|
}
|
||||||
|
|
||||||
var RemapKey = map[fyne.KeyName]byte{
|
var RemapKey = map[fyne.KeyName]byte{
|
||||||
fyne.KeyEscape: 0x1B,
|
fyne.KeyEscape: 0x1B,
|
||||||
fyne.KeyReturn: 0x0A,
|
fyne.KeyReturn: 0x0A,
|
||||||
@ -162,5 +193,4 @@ var RemapKeyShift = map[fyne.KeyName]byte{
|
|||||||
fyne.KeyAsterisk: 0x7E,
|
fyne.KeyAsterisk: 0x7E,
|
||||||
fyne.KeyPlus: 0x7E,
|
fyne.KeyPlus: 0x7E,
|
||||||
fyne.KeyBackTick: 0x60,
|
fyne.KeyBackTick: 0x60,
|
||||||
fyne.KeyUnknown: 0x00,
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
package usart
|
package usart
|
||||||
|
|
||||||
|
import log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Universal Serial Asynchronous Receiver/Transmitter
|
Universal Serial Asynchronous Receiver/Transmitter
|
||||||
i8051, MSM82C51, КР580ВВ51
|
i8051, MSM82C51, КР580ВВ51
|
||||||
@ -133,12 +135,19 @@ func (s *I8251) Send(value byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *I8251) Receive() byte {
|
func (s *I8251) Receive() byte {
|
||||||
|
|
||||||
if s.rxe {
|
if s.rxe {
|
||||||
if len(s.bufferRx) > 0 {
|
if len(s.bufferRx) > 0 {
|
||||||
res := s.bufferRx[0]
|
res := s.bufferRx[0]
|
||||||
s.bufferRx = s.bufferRx[1:]
|
s.bufferRx = s.bufferRx[1:]
|
||||||
|
log.Debugf("ReceiveByte: %x", res)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
log.Debugf("ReceiveByte: empty buffer")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *I8251) SetRxBytes(bytes []byte) {
|
||||||
|
s.bufferRx = append(s.bufferRx, bytes...)
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user