home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
SIMTEL
/
HITECH-C
/
Z8051H83.EXE
/
FEATZ80.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-05-21
|
5KB
|
161 lines
#include <intrpt.h>
/*
* This source file demonstrates some of the special features
* of the HI-TECH Z80/Z180/64180 C Cross Compiler. This file should
* be compiled with Z80 or Z180 code generation selected.
*
* To generate the best possible code from this source file, select
* Z180 code generation from the "Options" menu and "Full Optimization"
* from the "Optimization" menu. This will demonstrate the quality of
* code which can be obtained using HI-TECH C, for a fraction of the
* effort required to write equivalent assember code.
*
* HI-TECH C has a number of features designed to make programming
* embedded processors simpler and more efficient, these include:
*
* interrupt functions: interrupt handlers may be written entirely
* in C (no messy assembler code required).
* The Z80 cross compiler also allows functions
* to be declared as "fast interrupt" or
* "nmi interrupt".
*
* "nmi interrupt" functions return with a RETN
* instruction.
*
* "fast interrupt" functions preserve the
* general purpose register using the EXX and
* EX AF,AF' instructions, thereby saving the
* overhead of pushing registers onto the stack
*
* port variables: Z80 ports can be accessed directly from
* C - just like any other variable or
* memory location.
*
* absolute variables: variables of any type (even complex
* structures and arrays) can be placed at
* any absolute address in memory - great
* for handling memory mapped devices.
*
* in-line assembler: assembler code can be place in line. This
* is useful for accessing special instructions.
*
* register arguments: some function arguments are passed in
* the DE and BC registers. Register based
* argument passing is much faster and more
* compact than stack based passing.
*/
#ifndef z80
#error This program should be compiled to Z80/Z180 code
#endif
volatile port unsigned char SIO_CMD @ 0x20; /* SIO command reg */
volatile port unsigned char SIO_DATA @ 0x21; /* SIO data reg */
volatile unsigned char PIA_STATUS @ 0xFF80; /* mem mapped PIA */
volatile unsigned char PIA_BUFFER @ 0xFF81; /* at FF80 - FF81 */
unsigned char rxbuf[256]; /* 256 byte circular buffer */
unsigned char ri_ptr, ro_ptr; /* head, tail pointers */
/*
* rx_intr handles receive interrupts from a Z80 sio
*/
fast interrupt void
rx_intr(void)
{
rxbuf[ri_ptr++] = SIO_DATA;
if (ro_ptr == ri_ptr) /* buffer overflow ? */
--ri_ptr; /* discard last byte received */
}
/*
* sio_char_avail: returns 1 if a char is available, 0 otherwise
*/
unsigned char
sio_char_avail(void)
{
return (ri_ptr != ro_ptr);
}
/*
* sio_get_char: returns one char from the tail of the circular
* buffer. Assumes that a char is available.
*/
unsigned char
sio_get_char(void)
{
unsigned char ch;
di();
ch = rxbuf[ro_ptr++];
ei();
return ch;
}
/*
* Transmit a character via the memory mapped PIA
* bit 0 of STATUS register indicates it is ready to accept data
*
* Note: register based argument passing is used with this
* function. "ch" will be passed in the E register. If FULL
* optimization is performed, "ch" probably won't ever be stored
* to a stack location.
*/
void
pia_send(unsigned char ch)
{
while (!(PIA_STATUS & 1))
continue;
PIA_BUFFER = ch;
}
/*
* Initialize the SIO and PIA - demo code only, not intended to be
* an accurate example of Z80 SIO programming
*
* Notes: the post-pass optimizer will eliminate redundant LD BC,xxx
* instructions in the SIO init code sequence.
*
* If Z180 code is selected, OUT0 instructions will be used
* instead of OUT (C),A. The full version of the compiler
* allows the user to specify whether port I/O code is to
* be generated for 8 or 16 bit port address decoding.
*/
void
device_inits(void)
{
di(); /* interrupts of while programming devices */
#asm
IM 2 ;interrupt mode 2
LD A,0xFF ;vector page: 0xFF00 - 0xFFFF
LD I,A
#endasm
SIO_CMD = 0x01; /* write to register 1 */
SIO_CMD = 0xC1; /* register 1 = 0xC1 */
SIO_CMD = 0x02; /* write to register 2 */
SIO_CMD = 0x3E; /* register 2 = 0x3E */
SIO_CMD = 0x06; /* register 6: interrupt vector */
SIO_CMD = 0x10; /* vector: 0xFF10 */
set_vector((isr *) 0xFF10, rx_intr);
PIA_STATUS = 0x80; /* reset PIA */
PIA_STATUS = 0x40; /* mode 2: bidirectional, interrupts off */
ei();
}
main()
{
device_inits();
for (;;) {
if (sio_char_avail())
pia_send(sio_get_char());
/* other processing */
}
}