;               SetPins v1.0  by MICHAL JARZYNSKI  (26.08.97)
;                       This program is PUBLIC DOMAIN.
;
;             Kod śródīowy byī sprawdzany pod makroasemblerami:
;
;                  PhxAss v4.32 - copyright by Frank Wille
;                   SNMA v2.04 - copyright by Samu Nuojua
;
;      Niestety program ten nie chciaī siė skompilowaź pod A68K v2.71.
;      Gīównym powodem byīo uūywanie etykiet lokalnych, ale ta wersja,
;     którā posiadam (2.71) jest aū z 1991 roku. Byź moūe nowsze wersje
;                              sā duūo lepsze.
;
;
;    Program ten pozwala na ustawienie poziomów logicznych na niektórych
;      wyjōciach portów: równolegīego, szeregowego i joysticka. Uūycie
;         skompilowanego programu jest proste. Za nazwā trzeba podaź
;      nazwy sygnaīów, które majā byź ustawione, a zaraz za nimi cyfry
;      0 lub 1 oznaczajāce niski lub wysoki stan napiėcia na wyjōciu. 
;
;                     np.  SetPins POUT=0 SELT=0 FIRE=1
;
;Powyūsze polecenie spowoduje, ūe sygnaīy POUT i SELECT w porcie równolegīym
;oraz FIRE w porcie joysticka (nie myszy!) zostanā ukierunkowane na wyjōcie,
;   a przy tym dwa pierwsze ustawiā siė na poziomie niskim (0V), a trzeci
;          bėdzie od tej chwili cieszyī siė poziomem wysokim (+5V).
;
;    Moūna teū stworzyź sobie plik z danymi o poziomach, i podaź go tak:
;
;                           SetPins -example.data
;
;                                  UWAGA 1:
;Nieco inaczej jest z wyjōciami na porcie szeregowym. Stan 0 oznacza na nich
;          napiėcie +12V, a 1 zmienia poziom wtedy na -5V (minus).
;
;                                  UWAGA 2:
;Mimo ūe moja dokumentacja gīosi, ūe moūna takūe zmieniaź sygnaīy CTS (pin 5),
;  DSR (6) oraz DCD (8), to jednak moje pomiary speīzīy na niczym. Mimo to
; pozostawiīem to wyjōcia. Byź moūe moja AMIGA ma uszkodzony port szeregowy,
;tego nie wiem, a nie miaīem gdzie tego sprawdziź (narazie nie mam w zasiėgu
;                           rėki ūadnego AMIGOS).
;
;

; dos.library functions
_LVOOpen		equ	-30
_LVOClose		equ	-36
_LVORead		equ	-42
_LVOWrite		equ	-48
_LVOOutput		equ	-60
_LVOStrToLong	equ	-816

; exec.library functions
_LVOCloseLibrary	equ	-414
_LVOOpenLibrary		equ	-552

EXECBASE		equ	4.w						; baza biblioteki exec pod etykietā EXECBASE
MODE_OLDFILE	equ	1005

	SECTION		PROGRAM,CODE

	bra		_main_program
	dc.b	"$VER: SetPins 1.0 by Michal Jarzynski <PL>  (26.08.97)",0
			even
rmb:
	btst	#2,$dff016
	bne		rmb
	rts


_main_program:
;	bsr		rmb
	bsr		_copy_line_command	; skopiowanie do bufora linii komend
	bsr		_open_dos			; otwarcie biblioteki dos.library	
	beq		_no_dos				; ... a gdy nie otworzyīa siė dos.library to =>_no_dos
	bsr		_get_output			; pobranie adresu konsoli
	link	a5,#-200			; zarezerwowanie na stosie 200 bajtów dla A5
	bsr		_go_main			; wykonanie gīównej procedury
	unlk	a5					; zwolnienie ze stosu 200 bajtów
	bsr		_close_dos			; zamkniėcie dos.library
_no_dos:
	rts							; no i koniec programu !!!

_open_dos:
	move.l	EXECBASE,a6				; a6 <- baza biblioteki exec.library
	lea		dos_name(pc),a1			; a1 <- adres, gdzie jest nazwa biblioteki dos
	moveq	#0,d0					; d0 <- nr. wersji biblioteki (0 = obojėtna)
	jsr		_LVOOpenLibrary(a6)		; otwarcie biblioteki
	move.l	d0,dos_base				; przepisanie adresu otwartej biblioteki do "dos_base"
	rts

_close_dos:
	move.l	dos_base,a1				; a1 <- baza biblioteki dos.library
	move.l	EXECBASE,a6				; a6 <- baza biblioteki exec.library
	jsr		_LVOCloseLibrary(a6)	; zamkniėcie biblioteki
	rts

_get_output:					; ------------------------------------
	move.l	dos_base(pc),a6		; Procedura pobierajāca adres konsoli,
	jsr		_LVOOutput(a6)		; z której uruchomiony byī program
	move.l	d0,output
	rts

_copy_line_command:					; --------------------------------------------
	move.l	d0,d2					; Ta procedura kopiuje znaki podane za nazwā
	lea		line_command_buffer,a1	; programu (w CLI) do bufora.
	tst.l	d0						; W D0 mamy dīugoōź tego ciāgu,
	beq		_no_line_command		; a w A0 - adres, pod którym leūy interesujācy 
		sub.l	#1,d0				; nas obszar pamiėci.                         
.loop:
		move.b	(a0)+,(a1)+
		dbf		d0,.loop

	lea		line_command_buffer,a1
	move.l	d2,d0
	bsr		_upper_string
_no_line_command:
	move.b	#0,(a1)
	rts

_upper_string:					; -------------------------------------------------
.loop:							; Procedurka zamieniajāca wszystkie znaki w buforze
		move.b	(a1),d1			; na ich duūe odpowiedniki.
		cmp.b	#"*",d1
		beq		.end_string
		cmp.b	#122,d1
		bhi		.skip
		cmp.b	#96,d1
		bls		.skip
		sub.b	#32,d1
.skip:
		move.b	d1,(a1)+
		dbf		d0,.loop
	rts
.end_string:
	move.b	#0,(a0)+
	move.b	#0,(a0)
	rts

_print_info:					; ----------------------------------------------------
	move.l	output,d1			; Wyōwietlenie informacji o programie, gdy uūytkownik
	beq		.no_output			; nie wpisaī ūadnych danych, lub wpisaī znak zapytania
	move.l	#prog_info,d2
	move.l	#prog_info_end-prog_info,d3
	move.l	dos_base(pc),a6
	jsr		_LVOWrite(a6)
.no_output:
	rts

_print_error:					; ---------------------------------------------------
	move.l	output,d1			; Tutaj wyōwietla siė ewentualny bīād, gdy uūytkownik
	beq		.no_output			; bīėdnie podaī dane do programu
	move.l	#err_info,d2
	move.l	#err_info_end-err_info,d3
	move.l	dos_base(pc),a6
	jsr		_LVOWrite(a6)
.no_output:
	rts

_print_file_error:				; -------------------------------------------
	move.l	output,d1			; A tutaj informujemy uūytkownika o kīopotach
	beq		.no_output			; z podanym plikiem.
	move.l	#file_info,d2
	move.l	#file_info_end-file_info,d3
	move.l	dos_base(pc),a6
	jsr		_LVOWrite(a6)
.no_output:
	rts


output:		dc.l	0
dos_base:	dc.l	0
dos_name:	dc.b	"dos.library",0
prog_info:	
	dc.b	"",10
	dc.b	"    SetPins v1.0 by MICHAL JARZYNSKI  (POLAND  26.VIII.97)",10
	dc.b	"    ------------------------------------------------------",10
	dc.b	"",10
	dc.b	"    Usage:    SetPins  signal=0/1   signal=0/1   ...",10
	dc.b	"              SetPins  -filename",10
	dc.b	"",10
	dc.b	"  signal - one of signals in parallel, serial or joystick port:",10
	dc.b	"",10
	dc.b	"       signal port pin  vol.0/1      signal port pin  vol.0/1",10
	dc.b	"       DAT0-7  par 2-9   0/+5 V       SDSR   ser   6  +12/-5 V",10
	dc.b	"        BUSY   par  11   0/+5 V       SCTS   ser   5  +12/-5 V",10
	dc.b	"        POUT   par  12   0/+5 V       SDCD   ser   8  +12/-5 V",10
	dc.b	"        SELT   par  13   0/+5 V       SRTS   ser   4  +12/-5 V",10
	dc.b	"        FIRE  joy2   6   0/+5 V       SDTR   ser  20  +12/-5 V",10
	dc.b	"",10
	dc.b	"  0/1 - set low (0) or high (1) level on pin",10
	dc.b	"  filename - file with signals set defines",10
	dc.b	"",10
prog_info_end:
err_info:
	dc.b	" --- SetPins v1.0 --- ERROR, correct your data !",10
err_info_end:
file_info:
	dc.b	" --- SetPins v1.0 --- ERROR, can't load data file !",10
file_info_end:
			even

_go_main:		; PONIEWAŪ UŪYWAMY STOSU z A5, TEGO REJESTRU NIE WOLNO TERAZ ZMIENIAŹ
	lea		line_command_buffer,a0	; a0 <- bufor z liniā wpisanā za nazwā prog. w CLI
	bsr		_usage					; sprawdś, czy trzeba wyōwietliź HELP
	bne		.no_usage				; => .no_usage, gdy przechodzimy do rzeczy
	bra		_print_info				; skocz do helpu, i tam juū zakoļcz tā procedurė
.no_usage:
	lea		line_command_buffer,a0
	tst.b	(a0)				; czy oby plik siė wczytaī ???
	beq		_print_file_error	;  ... jeōli nie to skocz tam, gdzie wyōwietli siė info
.loop1:
	bsr		_get_signal			; pobierz sygnaī i wyōlij na nasz adres i nr. bitu
	beq		.continue			; jeōli to koniec, to => .continue
	add.l	#1,s_count			; zwiėksz licznik "s_count" o jeden
	bra		.loop1				; ... i dalej powtarzaj to samo
.continue:

	move.l	s_count(pc),d7		; d7 <- licznik "s_count"
	beq		_print_error		; gdy licznik pusty, to wyōwietl HELP
	sub.l	#1,d7
.loop2:
	bsr		_put_signal			; ustaw odpowiedni bit (sygnaī na porcie)
	dbf		d7,.loop2			; powtórz tyle razy, ile byīo sygnaīów
	tst.b	data_error
	bne		_print_error
	rts

s_count:	dc.l	0			; to jest licznik iloōci ustawianych sygnaīów
data_error:	dc.w	0

_usage:					; --------------------------------------------------------
	move.l	a0,a1		; Procedura sprawdzajāca, czy uūytkownik wprowadziī jakieō
.loop:					; dane. Gdy wprowadziī znak zapytania, albo nic nie
	move.b	(a1)+,d1	; wprowadziī, to podprocedura ta ustawia wtedy
	cmp.b	#0,d1		; znacznik Z na zero, dziėki czemu potem program pozna,
	beq		.no_data	; czy wyōwietliź planszė z HELP'em, czy teū nie...
	cmp.b	#'?',d1
	beq		.no_data
	cmp.b	#'-',d1
	beq		_read_file
	cmp.b	#' ',d1
	beq		.loop
	cmp.b	#9,d1
	beq		.loop
	cmp.b	#10,d1
	beq		.loop
	cmp.b	#13,d1
	beq		.loop
	moveq	#1,d0
	rts
.no_data:
	moveq	#0,d0
	rts

_read_file:
	lea		line_command_buffer,a3		; a3 <- adres bufora na dane
.loop:
	move.b	(a1)+,d1			; d1 <- kolejny znak z bufora
	cmp.b	#" ",d1				; czy to spacja ???
	beq		.loop				;  ... to trzeba omināź
	cmp.b	#9,d1				; czy to tabulator ???
	beq		.loop				;  ... to trzeba omināź
	cmp.b	#0,d1				; czy to ZERO ???
	beq		.error_file			;  ... to trzeba wyskoczyź, => .error_file
	cmp.b	#34,d1				; czy to cudzysīów ???
	beq		.quotes				;  ... to trzeba => .quotes
		sub.l	#1,a1
		move.l	a1,-(sp)		; na stosie odkīadamy adres nazwy pliku
		add.l	#1,a1
		bra		.loop2			; skaczemy do obsīugi bez cudzysīowiów
.quotes:
	move.l	a1,-(sp)
.loop3:					; tu jest obsīuga z cudzysīowiami
	move.b	(a1)+,d1		; d1 <- nastėpny znak
	cmp.b	#34,d1			; czy to cudzysīów ???
	beq		.end_name		;  ... jeōli tak to => .end_name
	bra		.loop3	
.loop2:					; a tu obsīuga bez cudzysīowiów
	move.b	(a1)+,d1		; d1 <- nastėpny znak	
	cmp.b	#" ",d1			; czy to spacja ???
	beq		.end_name		;  ... jeōli tak to => .end_name
	cmp.b	#9,d1			; czy to tabulator ???
	beq		.end_name		;  ... jeōli tak to => .end_name
	cmp.b	#10,d1			; czy to enter ???
	beq		.end_name		;  ... jeōli tak to => .end_name
	cmp.b	#13,d1			; czy to pc-enter ???
	beq		.end_name		;  ... jeōli tak to => .end_name
	bra		.loop2			; i tak do oporu.
.end_name:
	move.b	#0,-(a1)		; a gdy wreszcie koniec, wtedy zaznacz koniec nazwy

	move.l	(sp)+,d1			; »»» poniūej otworzenie pliku
	move.l	#MODE_OLDFILE,d2
	move.l	dos_base(pc),a6
	jsr		_LVOOpen(a6)
	tst.l	d0
	beq		.error_file

	move.b	#0,(a3)

	move.l	d0,-(sp)			; »»» teraz próba odczytania jego 512 pierwszych bajtów
	move.l	d0,d1
	move.l	a3,d2
	move.l	#512,d3
	move.l	dos_base(pc),a6
	jsr		_LVORead(a6)

	move.l	a3,a1
	bsr		_upper_string		; powiėkszenie odczytanych liter

	move.l	(sp)+,d1			; »»» i zamkniėcie pliku
	move.l	dos_base(pc),a6
	jsr		_LVOClose(a6)
	moveq	#1,d0
	rts

.error_file:
	move.b	#0,(a3)
	moveq	#1,d0
	rts	

;-------------------------- Pobranie z linii komend na stos adresu zmienianego bitu
_get_signal:
	bsr		_get_symbol		; sprawdś, jaki jest nastėpny symbol (DAT0, itp...)
	beq		.no_data		; jeōli nie znaleziono, to wyjdś z podproceduty, => .no_data
	bsr		_get_sign		; sprawdś, jaki ma byź znak danego "pinu"
	beq		.no_data_fatal	; jeōli nie ma cyfry 0 lub 1, to wypad, => .no_data
		move.l	4(a1),-(a5)		; odīuū na stos adres do zmiany
		lsl.w	#4,d0			; niech w D0 znak (0 czy 1) bėdzie w starszej czėōci sīowa
		lsl.w	#4,d0
		move.b	8+3(a1),d0		; nr. bitu do mīodszego bajtu w D0
		move.w	d0,-(a5)		; caīy D0 na stos
		moveq	#1,d0
		rts
.no_data_fatal:
	st.b	data_error
.no_data:
	moveq	#0,d0
	rts

;-------------------------- Ustawienie ūādanego bitu w odpowiednim adresie
_put_signal:
	move.w	(a5)+,d0			; nr. bitu (i info. czy ma byź 0 czy 1)
	move.l	(a5)+,a0			; adres, gdzie ma byź zmieniony bit
		lea		$200(a0),a1		; adres, gdzie trzeba wstawiź 1, aby pin byī wyjōciem
		clr.l	d1
		move.b	d0,d1			; d1 <- nr. bitu
		bset.b	d1,(a1)			; ustawienie pina na wyjōcie
		lsr.w	#4,d0
		lsr.w	#4,d0
		sub.b	#1,d0			; d0 <- info, czy bit ma byź =1 czy =0
		beq		.low
		bset.b	d1,(a0)			; ustawienie pina na poziom wysoki
		rts
.low:		
		bclr.b	d1,(a0)			; ustawienie pina na poziom niski
	rts

;-------------------------- Pobranie z bufora, jaki byī ūādany sygnaī (DAT0, itp...)
_get_symbol:
.loop2:
	tst.b	(a0)					; czy juū koniec ciāgu ???
	beq		.end_string				; jeōli tak, to => .end_string
	move.l	#COUNT-1,d1				; d1 <- ile porównaļ ??? (17)
	clr.l	d0						; d0 - wskaśnik, który to ciāg wystāpiī (DAT0, itp)
	lea		address_list,a1			; a1 <- adres, gdzie sā porównywane ciāgi
.loop1:
		add.l	#1,d0			; d0 <- dodaź 1, bo narazie sprawdzamy z ciāgiem 1 (DAT0)

		move.b	(a1),d2
		cmp.b	(a0),d2 	; czy jest róūnica miėdzy pierszymi literami ?
		bne		.no_eq		; jeōli jest, to skacz dalej

		move.b	1(a1),d2
		cmp.b	1(a0),d2
		bne		.no_eq

		move.b	2(a1),d2
		cmp.b	2(a0),d2
		bne		.no_eq

		move.b	3(a1),d2
		cmp.b	3(a0),d2
		bne		.no_eq

		add.l	#4,a0	; jeōli caīoōź przeszīa, to znaczy, ūe to to. przesuļ a0 o 4
		tst.l	d0		; przed wyjōciem przetestuj D0
		rts				; wyjōcie z podprocedury
.no_eq:
	add.l	#3*4,a1		; przesuļ wskaśnik z tablicy porównywaļ do nastėpnego ciāgu (+12)
	dbf		d1,.loop1	; daj wszystko w pėtlė

	add.l	#1,a0		; jeōli caīa pėtla przeszīa, to przesuļ wskaśnik A0 o 1...
	bra		.loop2		; ... i dalej jazda
.end_string:
	moveq	#0,d0			; wyzeruj znacznik Z (zera)...
	rts					; ... i wyjdś z programu

;-------------------------- Pobranie informacji, czy bit ma byź ustawiony, czy skasowany
_get_sign:
.loop:
	move.b	(a0)+,d0	; d0 <- nastėpny znak z ciāgu
	cmp.b	#" ",d0		; czy to spacja ???
	beq		.loop		;   ... to powtórz próbė
	cmp.b	#9,d0		; czy to tabulator ???
	beq		.loop		;   ... to powtórz próbė
	cmp.b	#"=",d0		; czy to znak równoōci ???
	beq		.loop		;   ... to powtórz próbė
	cmp.b	#"0",d0		; czy to znak ZERO ???
	beq		.set_off	;   ... to ustaw na zero
	cmp.b	#"1",d0		; czy to znak JEDEN ???
	beq		.set_on		;   ... to ustaw na jeden
	sub.l	#1,a0		; gdy nie byīo ūadnych z tych znaków, to a0=a0-1...
	moveq	#0,d0			;  ... wyzeruj znacznik Z ...
	rts					;  ... i koļcz robotė w tej podprocedurze.

.set_off:
	moveq	#1,d0
	rts
.set_on:
	moveq	#2,d0
	rts

	; nazwa, adres ON/OFF, adres IN/OUT, nr. bitu

COUNT	equ	17					; --------------------------------------------------
address_list:					; Tutaj znajduje siė tabela z odpowiednimi symbolami
	dc.l	"DAT0",$bfe101,0	; i adresami do nich, a takūe numerami bitów.
	dc.l	"DAT1",$bfe101,1	; COUNT = 17 oznacza ile jest tych wszystkich
	dc.l	"DAT2",$bfe101,2	; moūliwych pinów do ustawienia.
	dc.l	"DAT3",$bfe101,3
	dc.l	"DAT4",$bfe101,4
	dc.l	"DAT5",$bfe101,5
	dc.l	"DAT6",$bfe101,6
	dc.l	"DAT7",$bfe101,7
	dc.l	"BUSY",$bfd000,0
	dc.l	"POUT",$bfd000,1
	dc.l	"SELT",$bfd000,2

	dc.l	"SDSR",$bfd000,3
	dc.l	"SCTS",$bfd000,4
	dc.l	"SDCD",$bfd000,5
	dc.l	"SRTS",$bfd000,6
	dc.l	"SDTR",$bfd000,7

	dc.l	"FIRE",$bfe001,7

	SECTION		DANE,BSS	; 
line_command_buffer:		; Zarezerwowanna przez ten chunk pamiėź bėdzie wykorzystana
		ds.b	512+16		; jako bufor na liniė komendy (oraz plik)
