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
|
||||
|
||||
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
|
||||
mformat -i $@ -t 40 -h 2 -s 9
|
||||
mcopy -i $@ polio.com ::/
|
||||
mcopy -i $@ polmon.com ::/
|
||||
mcopy -i $@ paracli.com ::/
|
||||
dd if=fat12boot.bin of=$@ conv=notrunc
|
||||
|
||||
.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