Add paracli, a parallel port comm utility
This commit is contained in:
6
Makefile
6
Makefile
@@ -48,11 +48,15 @@ wozmon.elf: CPPFLAGS += -DNOBPB
|
|||||||
|
|
||||||
wozmon.bin: wozmon.elf
|
wozmon.bin: wozmon.elf
|
||||||
|
|
||||||
polos.img: fat12boot.bin polmon.com polio.com
|
paracli.elf: LDFLAGS += -T doscom.ld
|
||||||
|
paracli.elf: paracli.s paracomm.o
|
||||||
|
|
||||||
|
polos.img: fat12boot.bin polmon.com polio.com paracli.com
|
||||||
dd if=/dev/zero of=$@ bs=512 count=720
|
dd if=/dev/zero of=$@ bs=512 count=720
|
||||||
mformat -i $@ -t 40 -h 2 -s 9
|
mformat -i $@ -t 40 -h 2 -s 9
|
||||||
mcopy -i $@ polio.com ::/
|
mcopy -i $@ polio.com ::/
|
||||||
mcopy -i $@ polmon.com ::/
|
mcopy -i $@ polmon.com ::/
|
||||||
|
mcopy -i $@ paracli.com ::/
|
||||||
dd if=fat12boot.bin of=$@ conv=notrunc
|
dd if=fat12boot.bin of=$@ conv=notrunc
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
|
20
doscom.ld
Normal file
20
doscom.ld
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
SECTIONS {
|
||||||
|
. = 0x100;
|
||||||
|
|
||||||
|
.text : {
|
||||||
|
KEEP(*(.init))
|
||||||
|
*(.text*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.rodata : {
|
||||||
|
*(.rodata*)
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss (NOLOAD) : {
|
||||||
|
* (.bss)
|
||||||
|
}
|
||||||
|
|
||||||
|
.data : {
|
||||||
|
*(.data)
|
||||||
|
}
|
||||||
|
}
|
80
paracli.s
Normal file
80
paracli.s
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
.arch i8086,jumps
|
||||||
|
.code16
|
||||||
|
.intel_syntax noprefix
|
||||||
|
|
||||||
|
.section .init
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
mov ax, cs
|
||||||
|
mov ds, ax
|
||||||
|
mov es, ax
|
||||||
|
cli
|
||||||
|
mov ss, ax
|
||||||
|
mov sp, 0x100
|
||||||
|
sti
|
||||||
|
jmp main
|
||||||
|
|
||||||
|
.section .text.parcb
|
||||||
|
parcb:
|
||||||
|
push bx
|
||||||
|
push si
|
||||||
|
push bp
|
||||||
|
mov si, ax
|
||||||
|
1:
|
||||||
|
test dx, dx
|
||||||
|
jz 0f
|
||||||
|
mov al, [si]
|
||||||
|
mov ah, 0x0e
|
||||||
|
mov bh, 0
|
||||||
|
int 0x10
|
||||||
|
dec dx
|
||||||
|
inc si
|
||||||
|
jmp 1b
|
||||||
|
0:
|
||||||
|
pop bp
|
||||||
|
pop si
|
||||||
|
pop bx
|
||||||
|
ret
|
||||||
|
|
||||||
|
.section .rodata.l0
|
||||||
|
.l0: .ascii "> "
|
||||||
|
.l1: .ascii "."
|
||||||
|
|
||||||
|
delay = 500
|
||||||
|
|
||||||
|
.section .text.main
|
||||||
|
.global main
|
||||||
|
main:
|
||||||
|
mov ax, 0x0002
|
||||||
|
int 0x10
|
||||||
|
mov ax, offset parcb
|
||||||
|
call paracomm_init
|
||||||
|
0:
|
||||||
|
mov ah, 0x01
|
||||||
|
int 0x16
|
||||||
|
jz 1f
|
||||||
|
mov ah, 0x00
|
||||||
|
int 0x16
|
||||||
|
mov ah, 0
|
||||||
|
call paracomm_send
|
||||||
|
test ax, ax
|
||||||
|
jz 0b
|
||||||
|
1:
|
||||||
|
call paracomm_nextbyte
|
||||||
|
mov dx, 0x3bc
|
||||||
|
out dx, al
|
||||||
|
add dl, 2
|
||||||
|
mov al, 1
|
||||||
|
out dx, al
|
||||||
|
mov cx, delay
|
||||||
|
2: loop 2b
|
||||||
|
mov al, 0
|
||||||
|
out dx, al
|
||||||
|
mov cx, delay
|
||||||
|
3: loop 3b
|
||||||
|
dec dl
|
||||||
|
in al, dx
|
||||||
|
mov cl, 4
|
||||||
|
shr al, cl
|
||||||
|
call paracomm_feed
|
||||||
|
jmp 0b
|
127
paracomm.c
Normal file
127
paracomm.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
#include "paracomm.h"
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define kMosiIdleByte 0x00
|
||||||
|
#define kMosiStartByte 0x42
|
||||||
|
#define kMisoIdleNibble 0x0
|
||||||
|
#define kMisoStartNibble 0xa
|
||||||
|
|
||||||
|
static uint8_t mosi_workbuf[2][256];
|
||||||
|
static uint8_t mosi_workbuf_idx;
|
||||||
|
static uint8_t mosi_workbuf_size;
|
||||||
|
|
||||||
|
static uint8_t* mosi_sendbuf;
|
||||||
|
static uint8_t mosi_size;
|
||||||
|
static uint8_t mosi_sent;
|
||||||
|
|
||||||
|
static uint8_t mosi_state;
|
||||||
|
|
||||||
|
static uint8_t miso_recvbuf[256];
|
||||||
|
static uint8_t miso_size;
|
||||||
|
static uint8_t miso_received_nibbles;
|
||||||
|
static uint8_t miso_state;
|
||||||
|
static void (*miso_cb)(const uint8_t*, uint8_t);
|
||||||
|
|
||||||
|
static void swapbuffers() {
|
||||||
|
mosi_sendbuf = mosi_workbuf[mosi_workbuf_idx];
|
||||||
|
mosi_size = mosi_workbuf_size;
|
||||||
|
|
||||||
|
mosi_workbuf_size = 0;
|
||||||
|
mosi_workbuf_idx = (mosi_workbuf_idx + 1) % 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t paracomm_nextbyte() {
|
||||||
|
switch (mosi_state) {
|
||||||
|
case 0:
|
||||||
|
if (mosi_size == 0) {
|
||||||
|
swapbuffers();
|
||||||
|
if (mosi_size == 0) {
|
||||||
|
return kMosiIdleByte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mosi_state = 1;
|
||||||
|
return kMosiStartByte;
|
||||||
|
case 1:
|
||||||
|
// assert(mosi_size > 0)
|
||||||
|
mosi_sent = 0;
|
||||||
|
mosi_state = 2;
|
||||||
|
return mosi_size;
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
uint8_t b = mosi_sendbuf[mosi_sent];
|
||||||
|
mosi_sent += 1;
|
||||||
|
|
||||||
|
if (mosi_sent == mosi_size) {
|
||||||
|
swapbuffers();
|
||||||
|
mosi_state = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void paracomm_feed(uint8_t n) {
|
||||||
|
switch (miso_state) {
|
||||||
|
case 0:
|
||||||
|
if (n == kMisoStartNibble) {
|
||||||
|
miso_state = 1;
|
||||||
|
} else if (n == kMisoIdleNibble) {
|
||||||
|
} else {
|
||||||
|
// error: spurious nibble
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
miso_size = n;
|
||||||
|
miso_state = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
miso_size += n << 4;
|
||||||
|
miso_received_nibbles = 0;
|
||||||
|
miso_state = 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
{
|
||||||
|
uint8_t idx = miso_received_nibbles / 2;
|
||||||
|
if (miso_received_nibbles % 2 == 0) {
|
||||||
|
miso_recvbuf[idx] = n;
|
||||||
|
} else {
|
||||||
|
miso_recvbuf[idx] += n << 4;
|
||||||
|
}
|
||||||
|
miso_received_nibbles += 1;
|
||||||
|
|
||||||
|
if (miso_received_nibbles == 2*miso_size) {
|
||||||
|
if (miso_cb != 0) {
|
||||||
|
miso_cb(miso_recvbuf, miso_size);
|
||||||
|
}
|
||||||
|
miso_state = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void paracomm_init(miso_cb_t cb) {
|
||||||
|
mosi_size = 0;
|
||||||
|
mosi_workbuf_idx = 0;
|
||||||
|
mosi_workbuf_size = 0;
|
||||||
|
mosi_state = 0;
|
||||||
|
|
||||||
|
miso_state = 0;
|
||||||
|
miso_cb = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
int paracomm_send(uint8_t b) {
|
||||||
|
if (mosi_workbuf_size == 256) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* buff = mosi_workbuf[mosi_workbuf_idx];
|
||||||
|
buff[mosi_workbuf_size] = b;
|
||||||
|
mosi_workbuf_size += 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
19
paracomm.h
Normal file
19
paracomm.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef void (*miso_cb_t)(const uint8_t* buff, uint8_t size);
|
||||||
|
|
||||||
|
/** Must call first **/
|
||||||
|
void paracomm_init(miso_cb_t miso_cb);
|
||||||
|
|
||||||
|
/** Sends a single byte.
|
||||||
|
* Returns: 0 if no error, non-0 otherwise.
|
||||||
|
*/
|
||||||
|
int paracomm_send(uint8_t b);
|
||||||
|
|
||||||
|
/** Call after reading a nibble from the port */
|
||||||
|
void paracomm_feed(uint8_t n);
|
||||||
|
|
||||||
|
/** Yields the next byte to send out the port */
|
||||||
|
uint8_t paracomm_nextbyte();
|
Reference in New Issue
Block a user