I wanted to see how easy it would be to use my new DTMF Decoder module for the RC2014 from C.
I have previously written about using the z88dk C compiler to target the RC2014. However, I’ve not tried to use Z80 IO using the z88dk before.
To perform IO on the Z80 I needed to use a SFR (Special Function Register). When a variable created using an SFR is read or written to, this is converted directly into Z80 in and out instructions.
My DTMF Decoder module is running on an RC2014 Classic 2 on IO port 1. To declare an SFR in my C code to access this port, I can use the following…
#define __IO_DTMF_PORT 0x01
__sfr __at __IO_DTMF_PORT io_dtmf;
Now when I read from variable io_dtmf, this is mapped to an in instruction on the Z80. So to read this port, I can do the following…
uint8_t in = io_dtmf;
Now the unsigned 8 bit integer variable “in” holds the value of whatever was on IO port 1 when the variable was assigned.
To write the decoder program, I can use the same approach as my earlier Z80 assembly language program. This reading the IO port, and seeing if the STQ bit is set. If it is, we can then read the input and map this to the known DTMF codes. This is then printed to the console. We also need to make sure we’ve not already handled the current tone, so we need to store and check against this.
This is my working C code to decode incoming DTMF tones using my DTMF Decoder module for the RC2014.
// zcc +rc2014 -subtype=basic -clib=sdcc_iy -v -m -SO3 --max-allocs-per-node200000 dtmf.c -o dtmf -create-app
// this will compile to $8000, so can be run in SCM using "g 8000"
#pragma output CRT_ORG_CODE = 0x8000
#pragma output REGISTER_SP = 0xFC00
#define __IO_DTMF_PORT 0x01
__sfr __at __IO_DTMF_PORT io_dtmf;
#include <stdio.h>
char *codes = "D1234567890*#ABC";
uint8_t previous = 0xff;
void main(void) {
printf("DTMF Decoder\n");
while (1) {
uint8_t in = io_dtmf;
// is the STQ bit set?
if (in & 0b00010000) {
// we only want the lower 4 bits so mask out any others.
uint8_t current = in & 0b00001111;
if (current != previous) {
printf("%c", codes[current]);
previous = current;
}
} else {
previous = 0xff;
}
}
}