mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
somewhat accurate baud rate delay simulator
This commit is contained in:
@@ -196,7 +196,9 @@ VRAM Bank 0 (256 kB)
|
||||
|
||||
Endianness: little
|
||||
|
||||
From the start of the memory space:
|
||||
|
||||
Memory Space
|
||||
|
||||
250880 bytes
|
||||
Framebuffer
|
||||
3 bytes
|
||||
@@ -675,6 +677,9 @@ Sound Adapter
|
||||
|
||||
Endianness: little
|
||||
|
||||
|
||||
Memory Space
|
||||
|
||||
0..114687 RW: Sample bin
|
||||
114688..131071 RW: Instrument bin (256 instruments, 64 bytes each)
|
||||
131072..196607 RW: Play data 1
|
||||
@@ -833,3 +838,68 @@ MMIO
|
||||
92..103 RW : DMA Lane 6 Props
|
||||
104..115 RW : DMA Lane 7 Props
|
||||
116..127 RW : DMA Lane 8 Props
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
High Speed Disk Peripheral Adapter (HSDPA)
|
||||
|
||||
Endianness: Little
|
||||
|
||||
MMIO
|
||||
|
||||
0..2 RW: Block transfer status for Disk 1
|
||||
0b nnnn nnnn, nnnn nnnn , a00z mmmm
|
||||
|
||||
n-read: size of the block from the other device, LSB (1048576-full block size is zero)
|
||||
m-read: size of the block from the other device, MSB (1048576-full block size is zero)
|
||||
a-read: if the other device hasNext (doYouHaveNext), false if device not present
|
||||
z-read: set if the size is actually 0 instead of 1048576 (overrides n and m parameters)
|
||||
|
||||
n-write: size of the block I'm sending, LSB (1048576-full block size is zero)
|
||||
m-write: size of the block I'm sending, MSB (1048576-full block size is zero)
|
||||
a-write: if there's more to send (hasNext)
|
||||
z-write: set if the size is actually 0 instead of 1048576 (overrides n and m parameters)
|
||||
3..5 RW: Block transfer status for Disk 2
|
||||
6..8 RW: Block transfer status for Disk 3
|
||||
9..11 RW: Block transfer status for Disk 4
|
||||
12..15 RW: Block transfer control for Disk 1 through 4
|
||||
0b 0000 abcd
|
||||
|
||||
a: 1 for send, 0 for receive
|
||||
|
||||
b-write: 1 to start sending if a-bit is set; if a-bit is unset, make other device to start sending
|
||||
b-read: if this bit is set, you're currently receiving something (aka busy)
|
||||
|
||||
c-write: I'm ready to receive
|
||||
c-read: Are you ready to receive?
|
||||
|
||||
d-read: Are you there? (if the other device's recipient is myself)
|
||||
|
||||
NOTE: not ready AND not busy (bits b and d set when read) means the device is not connected to the port
|
||||
16..19 RW: 8-bit status code for the disk
|
||||
20 RW: Currently active disk (0: deselect all disk, 1: select disk #1, ...)
|
||||
|
||||
Selecting a disk will automatically unset and hold down "I'm ready to receive" flags of the other disks,
|
||||
however, the target disk will NOT have its "I'm ready to receive" flag automatically set.
|
||||
|
||||
-- SEQUENTIAL IO SUPPORT MODULE --
|
||||
|
||||
NOTE: Sequential I/O will clobber the peripheral memory space.
|
||||
|
||||
256..257 RW: Sequential I/O control flags
|
||||
|
||||
258 RW: Opcode
|
||||
0x00 - No operation
|
||||
0x01 - Skip (arg 1) bytes
|
||||
0x02 - Read (arg 1) bytes and store to core memory pointer (arg 2)
|
||||
0x03 - Write (arg 1) bytes using data from the core memory from pointer (arg 2)
|
||||
0xFF - Terminate sequential I/O session and free up the memory space
|
||||
259..261 RW: Argument #1
|
||||
262..264 RW: Argument #2
|
||||
265..267 RW: Argument #3
|
||||
268..270 RW: Argument #4
|
||||
|
||||
|
||||
Memory Space
|
||||
|
||||
0..1048575 RW: Buffer for the block transfer lane
|
||||
|
||||
@@ -3,7 +3,7 @@ package net.torvald.tsvm.peripheral
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolean) {
|
||||
abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolean, val baudRate: Int = 20_000_000) {
|
||||
|
||||
var recipient: BlockTransferInterface? = null; protected set
|
||||
|
||||
@@ -34,7 +34,9 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
|
||||
ready.setRelease(false)
|
||||
|
||||
recipient?.let {
|
||||
this.blockSize.set(startSendImpl(it))
|
||||
val bytesSent = startSendImpl(it)
|
||||
this.blockSize.set(bytesSent)
|
||||
applyBaudRateDelay(bytesSent)
|
||||
//println("[BlockTransferInterface.startSend()] recipients blocksize = ${this.blockSize}")
|
||||
}
|
||||
|
||||
@@ -60,8 +62,13 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
|
||||
fun writeout(inputData: ByteArray) {
|
||||
busy.setRelease(true)
|
||||
ready.setRelease(false)
|
||||
blockSize.setRelease(minOf(inputData.size, BLOCK_SIZE))
|
||||
|
||||
val bytesReceived = minOf(inputData.size, BLOCK_SIZE)
|
||||
blockSize.setRelease(bytesReceived)
|
||||
writeoutImpl(inputData)
|
||||
|
||||
applyBaudRateDelay(bytesReceived)
|
||||
|
||||
busy.setRelease(false)
|
||||
ready.setRelease(true)
|
||||
}
|
||||
@@ -90,6 +97,38 @@ abstract class BlockTransferInterface(val isMaster: Boolean, val isSlave: Boolea
|
||||
const val UNIT_SEP = 0x1F.toByte()
|
||||
const val END_OF_SEND_BLOCK = 0x17.toByte()
|
||||
}
|
||||
|
||||
|
||||
private var lastTransmissionTime = 0L
|
||||
|
||||
/**
|
||||
* Calculates and applies appropriate delay based on data size and baud rate
|
||||
* @param byteCount Number of bytes being transmitted
|
||||
*/
|
||||
protected fun applyBaudRateDelay(byteCount: Int) {
|
||||
// Calculate delay in milliseconds
|
||||
// Baud rate is bits per second, and we assume 10 bits per byte (8 data bits + start/stop bits)
|
||||
val bitsTransmitted = byteCount * 10
|
||||
val expectedTransmissionTimeMs = (bitsTransmitted * 1000L) / baudRate
|
||||
|
||||
val currentTime = System.nanoTime() / 1000000L
|
||||
val elapsedTime = if (lastTransmissionTime > 0) currentTime - lastTransmissionTime else 0
|
||||
|
||||
// Only sleep if we need to slow down the transmission
|
||||
if (elapsedTime < expectedTransmissionTimeMs) {
|
||||
val sleepTime = expectedTransmissionTimeMs - elapsedTime
|
||||
try {
|
||||
Thread.sleep(sleepTime)
|
||||
println("Sleep $sleepTime ms for $byteCount bytes")
|
||||
}
|
||||
catch (e: InterruptedException) {
|
||||
// Handle interruption if needed
|
||||
}
|
||||
}
|
||||
|
||||
// Update last transmission time
|
||||
lastTransmissionTime = System.nanoTime() / 1000000L
|
||||
}
|
||||
}
|
||||
|
||||
fun ByteArray.trimNull(): ByteArray {
|
||||
|
||||
Reference in New Issue
Block a user