Hello,apologies if this is a simple question but how are you meant to access digital IO ports under CPM please?I am running ROMWBW, CP/M 2.2 - trying to access a SC129 digital IO card.But I am missing something as the old CPM BDOS call function doesn't seem to work?Z88DK within stdio.h includes cpm.h ( when I use the +cpm I believe using zcc ) but then claims:
Or do I need a patch/different library/compile a different library to make this function work?
Anyway my incantation as you call it is:zcc +cpm -vn -O3 -startup=0 -clib=new pushio.c -o pushio -lm -create-app
which seems pretty standard and vanilla to me - but please correct if I am missed something.Ahh, dinosaur brain slowly waking up to old world here - do I need to do -o on cpm_crt.asm or is the object already included??
Nope - or have a missed a compile stage that i need to do when including +cpm ?
First reading is (without testing) that is should work, if you're using the "classic" library.If you're using the "new" library, you may need to add the #include <cpm.h> file specifically. And the BDOS function name is then cpm_bdos(func,arg), or cpm_bdos_hl(func,arg).There's a bit of a description here on RC2014 that goes into the differences. It might be useful to have a look at that, if you've not already found it. Look for Libraries.
Thanks Steven but I have messed up here....
Just reread the documentation. That won't let me do the equivalent of "out port,value" as in basic will it as part of the disk operating system!
Muppet!
Is there not a simple function already in CPM.h for writing a byte to a given digital Io port number? Or do they assume everyone accessing it will do so from assembly??
Is it wrong I am enjoying not knowing and learning again???!! :-)
Thanks,
David
But could you double check the link please as it fails and doesn't work for me?
Thank you,
David
/* * Arfon speach synthesizer driver * uses RC2014 sound card i/o ports * Compiled to .com file with z88dk - sdcc * PS C:\z88dk\rc2014> zcc +rc2014 -subtype=hbios -v --list -m -SO3 --c-code-in-asm --opt-code-size -clib=sdcc_iy --max-allocs-per-node200000 iotest.c -o iotest -create-app * * D. Richards, Feb 2020*/
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <z80.h>
char * spk_dictionary[] = { "Digitalker", /* 0 */ "One", /* 1 */ "Two", /* 2 */ "Three", /* 3 */ "Four", /* 4 */ "Five", /* 5 */ "Six", /* 6 */ "Seven", /* 7 */ "Eight", /* 8 */ "Nine", /* 9 */
"Ten", /* 10 */ "Eleven", /* 11 */ "Twelve", /* 12 */ "Thirteen", /* 13 */ "Fourteen", /* 14 */ "Fifteen", /* 15 */ "Sizteen", /* 16 */ "Seventeen", /* 17 */ "Eighteen", /* 18 */ "Ninteen", /* 19 */
"Twenty", /* 20 */ "Thirty", /* 21 */ "Fourty", /* 22 */ "Fifty", /* 23 */ "Sixty", /* 24 */ "Seventy", /* 25 */ "Eighty", /* 26 */ "Ninety", /* 27 */ "Hundred", /* 28 */ "Thousand", /* 29 */
"Million", /* 30 */ "Zero", /* 31 */ "A", /* 32 */ "B", /* 33 */ "C", /* 34 */ "D", /* 35 */ "E", /* 36 */ "F", /* 37 */ "G", /* 38 */ "H", /* 39 */
"I", /* 40 */ "J", /* 41 */ "K", /* 42 */ "L", /* 43 */ "M", /* 44 */ "N", /* 45 */ "O", /* 46 */ "P", /* 47 */ "Q", /* 48 */ "R", /* 49 */
"S", /* 50 */ "T", /* 51 */ "U", /* 52 */ "V", /* 53 */ "W", /* 54 */ "X", /* 55 */ "Y", /* 56 */ "Z", /* 57 */ "Again", /* 58 */ "Ampere", /* 59 */
"And", /* 60 */ "At", /* 61 */ "Cancel", /* 62 */ "Case", /* 63 */ "Cent", /* 64 */ "400Hz", /* 65 */ "80Hz", /* 66 */ " ", /* 67 */ " ", /* 68 */ " ", /* 69 */
" ", /* 70 */ " ", /* 71 */ "Centi", /* 72 */ "Check", /* 73 */ "Comma", /* 74 */ "Control", /* 75 */ "Danger", /* 76 */ "Degree", /* 77 */ "Dollar", /* 78 */ "Down", /* 79 */
"Equal", /* 80 */ "Error", /* 81 */ "Feet", /* 82 */ "Flow", /* 83 */ "Fuel", /* 84 */ "Gallon", /* 85 */ "Go", /* 86 */ "Gram", /* 87 */ "Great", /* 88 */ "Greater", /* 89 */
"Have", /* 90 */ "High", /* 91 */ "Higher", /* 92 */ "Hour", /* 93 */ "In", /* 94 */ "Inches", /* 95 */ "Is", /* 96 */ "It", /* 97 */ "Kilo", /* 98 */ "Left", /* 99 */
"Less", /* 100 */ "Lesser", /* 101 */ "Limit", /* 102 */ "Low", /* 103 */ "Lower", /* 104 */ "Mark", /* 105 */ "Meter", /* 106 */ "Mile", /* 107 */ "Milli", /* 108 */ "Minus", /* 109 */
"Minute", /* 110 */ "Near", /* 111 */ "Number", /* 112 */ "Of", /* 113 */ "Off", /* 114 */ "On", /* 115 */ "Out", /* 116 */ "Over", /* 117 */ "Parenthesis", /* 118 */ "Percent", /* 119 */
"Please", /* 120 */ "Plus", /* 121 */ "Point", /* 122 */ "Pound", /* 123 */ "Pulses", /* 124 */ "Rate", /* 125 */ "Re", /* 126 */ "Ready", /* 127 */ "Right", /* 128 */ "s", /* 129 */
"Second", /* 130 */ "Set", /* 131 */ "Space", /* 132 */ "Speed", /* 133 */ "Star", /* 134 */ "Start", /* 135 */ "Stop", /* 136 */ "Than", /* 137 */ "The", /* 138 */ "Time", /* 139 */
"Try", /* 140 */ "Up", /* 141 */ "Volt", /* 142 */ "Weight" /* 143 */
};
#define SPK_DICTIONARY_COUNT ( sizeof( spk_dictionary ) / sizeof( char * ) )
void init(void){ z80_outp(0xd8,0x07); // a & b outputs z80_outp(0xd0,0xc0);
z80_outp(0xd8,0x0f); // clear b z80_outp(0xd0,0x00);
z80_outp(0xd8,0x0e); // clear a z80_outp(0xd0,0x00);}
void wait(void) // wait for Int after speach is finished{ int wd=0; int ia;
z80_outp(0xd8,0x07); // select ddr register z80_outp(0xd0,0x80); // set a inputs, b outputs
for(wd=0; wd<32000; wd++) { z80_outp(0xd8,0x0e); // select a ia=z80_inp(0xd8); // read a
if(ia&0x80) // check for int high { break; } } z80_outp(0xd8,0x07); // restor a & b as outputs z80_outp(0xd0,0xc0); return;}
void say(int i) // send speach index, then strobe{ z80_outp(0xd8,0x0e); // select a z80_outp(0xd0,0x00); // set low
z80_outp(0xd8,0x0f); // select b z80_outp(0xd0,i); // set key
z80_outp(0xd8,0x0e); // select a z80_outp(0xd0,0x01); // set strobe
wait();}
int find(char * inword, int *key) // lookup index for word to say{ int i; int value; for(i=0; i<SPK_DICTIONARY_COUNT; i++) { // try to convert text to non zero integer value = (int) strtol(inword, (char **)NULL, 10); if(value != 0) { *key = value; return 1; } // try to find word in dictionary if(strcmp(spk_dictionary[i], inword)==0) { *key = i; return 1; } } return 0;}
void main(void){ char buffer[80]; char * pch; int key=-1;
init(); do { printf("Words? "); scanf ("%s",buffer); pch = strtok (buffer,", .-"); while (pch != NULL) { if(find(pch, &key) == 1) { say(key); } pch = strtok (NULL, ", .-"); } } while (key != 0); }
Ummm, the link work for me, perhaps because I subscribe to the RC2014-Z80 group.here is the program, there is some useful discussion in the post as well though.
/** Arfon speach synthesizer driver* uses RC2014 sound card i/o ports* Compiled to .com file with z88dk - sdcc* PS C:\z88dk\rc2014> zcc +rc2014 -subtype=hbios -v --list -m -SO3 --c-code-in-asm --opt-code-size -clib=sdcc_iy --max-allocs-per-node200000 iotest.c -o iotest -create-app** D. Richards, Feb 2020*/
__sfr __at 13 port; // 8-bit i/o port at 13
int main(void) {
volatile unsigned char a;
a = port; // read port
port = 100; // write port
ret 0;
}
/* * Arfon speach synthesizer driver * uses RC2014 sound card i/o ports
* Compiled to .com (.bin) file with z88dk - sdcc * PS C:\z88dk\rc2014> zcc +rc2014 -subtype=hbios -v --list -m -SO3 --c-code-in-asm -clib=sdcc_iy --max-allocs-per-node200000 arfon.c -o arfon -create-app * * D. Richards, May 2020*/
#include <ctype.h>
#include <stdio.h>#include <string.h>#include <stdlib.h>#include <z80.h>
// 8 bit I/O ports#define IO_SR0 0xd0#define IO_SR8 0xd8
__sfr __at IO_SR0 s0;__sfr __at IO_SR8 s8;
const char * const spk_dictionary[] =
s8=0x07; // a & b outputs s0=0xc0; s8=0x0f; // clear b s0=0x00; s8=0xe0; s0=0x00;
}
void wait(void) // wait for Int after speach is finished{
volatile int ia; int wd=0;
s8=0x07; // select ddr register s0=0x80; // set a inputs, b outputs
for(wd=0; wd<32000; wd++) { s8=0x0e; // select a ia=s8; // read a
if(ia&0x80) // check for int high { break; } }
s8=0x07; // restor a & b as outputs s0=0xc0;
return;}
void say(int i) // send speach index, then strobe{
s8=0x0e; // select a s0=0x00; // set low
s8=0x0f; // select b s0=i; // set key
s8=0x0e; // select a s0=0x01; // set strobe
wait();}
int strcicmp(char const *a, char const *b){ for (;; a++, b++) { int d = tolower((unsigned char)*a) - tolower((unsigned char)*b); if (d != 0 || !*a) return d;
}}
int find(char * inword, int *key) // lookup index for word to say{ int i; int value; for(i=0; i<SPK_DICTIONARY_COUNT; i++) {
// try to convert text to non zero integer value = (int) strtol(inword, (char **)NULL, 10); if(value != 0) { *key = value; return 1; }
// try to find word in dictionary
if(strcicmp(spk_dictionary[i], inword)==0) { *key = i;// printf("key %d, Word %s\n",i,spk_dictionary[i]); return 1; } } return 0;}
int main(int argc, char* argv[])
{ char buffer[80]; char * pch; int key=-1;
int i;
init();
if(argc>1) {/* for(i=1; i<argc; i++) { printf("argc %d, argv=[%s]\n", i, argv[i]); }*/ for(i=1; i<argc; i++) { if(find(argv[i], &key)) { say(key);// printf("key %d = %s\n", key, spk_dictionary[key]); } }
} else { while (key!=0) { printf("\nWords? ");
scanf ("%s",buffer);
pch = strtok (buffer,", .-"); while (pch != NULL) { if(find(pch, &key) == 1) { say(key); } pch = strtok (NULL, ", .-"); } } }
return 0;}
The compiler output is a .bin file which needs to be renamed to .com, does anybody know if there is a way to force the creation of a .com using a command line override?
Attached is a re-written Arfon number speaking program, it takes a value on the command line and convers it to a spoken number.
it is loosely based on the code I found here: https://www.geeksforgeeks.org/program-to-convert-a-given-number-to-words-set-2/