{"id":2977,"date":"2025-01-01T14:36:46","date_gmt":"2025-01-01T14:36:46","guid":{"rendered":"https:\/\/www.robertprice.co.uk\/robblog\/?p=2977"},"modified":"2025-01-01T14:36:46","modified_gmt":"2025-01-01T14:36:46","slug":"using-the-dtmf-decoder-module-for-the-rc2014-from-c","status":"publish","type":"post","link":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/","title":{"rendered":"Using the DTMF Decoder Module for the RC2014 from C"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I wanted to see how easy it would be to use my new <a href=\"https:\/\/www.robertprice.co.uk\/robblog\/decoding-dtmf-tones-on-an-rc2014\/\">DTMF Decoder module for the RC2014<\/a> from C.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I have previously written about <a href=\"https:\/\/www.robertprice.co.uk\/robblog\/writing-c-code-for-the-rc2014-classic-ii-running-scm\/\">using the z88dk C compiler to target the RC2014<\/a>. However, I&#8217;ve not tried to use Z80 IO using the z88dk before.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To <a href=\"https:\/\/github.com\/z88dk\/z88dk\/wiki\/NewLib--Platform--Embedded#performing-io\">perform IO<\/a> 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.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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&#8230;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#define __IO_DTMF_PORT  0x01\n__sfr __at __IO_DTMF_PORT io_dtmf;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">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&#8230;<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>uint8_t in = io_dtmf;<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now the unsigned 8 bit integer variable &#8220;in&#8221; holds the value of whatever was on IO port 1 when the variable was assigned.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">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&#8217;ve not already handled the current tone, so we need to store and check against this.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is my working C code to decode incoming DTMF tones using my DTMF Decoder module for the RC2014.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ zcc +rc2014 -subtype=basic -clib=sdcc_iy -v -m -SO3 --max-allocs-per-node200000 dtmf.c -o dtmf -create-app\n\/\/ this will compile to $8000, so can be run in SCM using \"g 8000\"\n\n#pragma output CRT_ORG_CODE = 0x8000\n#pragma output REGISTER_SP = 0xFC00\n\n#define __IO_DTMF_PORT  0x01\n\n__sfr __at __IO_DTMF_PORT io_dtmf;\n\n#include &lt;stdio.h>\n\nchar *codes = \"D1234567890*#ABC\";\nuint8_t previous = 0xff;\n\nvoid main(void) {\n    printf(\"DTMF Decoder\\n\");\n    while (1) {\n        uint8_t in = io_dtmf;\n        \/\/ is the STQ bit set?\n        if (in &amp; 0b00010000) {\n            \/\/ we only want the lower 4 bits so mask out any others.\n            uint8_t current = in &amp; 0b00001111;\n            if (current != previous) {\n                printf(\"%c\", codes&#91;current]);\n                previous = current;\n            }\n        } else {\n            previous = 0xff;\n        }\n    }\n}<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>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&#8217;ve not tried to use Z80 IO using the z88dk before. To perform IO on the Z80 I needed &hellip; <a href=\"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Using the DTMF Decoder Module for the RC2014 from C&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":2971,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"inline_featured_image":false,"footnotes":""},"categories":[157],"tags":[159,117],"class_list":["post-2977","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-rc2014","tag-dtmf","tag-rc2014"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.7 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Using the DTMF Decoder Module for the RC2014 from C - Robert Price<\/title>\n<meta name=\"description\" content=\"Using z88dk to compile C code for the RC2014 that can decode incoming tones from the DTMF Decoder Module. This uses SFRs to handle Z80 IO.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/\" \/>\n<meta property=\"og:locale\" content=\"en_GB\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Using the DTMF Decoder Module for the RC2014 from C - Robert Price\" \/>\n<meta property=\"og:description\" content=\"Using z88dk to compile C code for the RC2014 that can decode incoming tones from the DTMF Decoder Module. This uses SFRs to handle Z80 IO.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/\" \/>\n<meta property=\"og:site_name\" content=\"Robert Price\" \/>\n<meta property=\"article:published_time\" content=\"2025-01-01T14:36:46+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.robertprice.co.uk\/robblog\/assets\/DTMF-Decoder-Module-For-RC2014.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"800\" \/>\n\t<meta property=\"og:image:height\" content=\"460\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"rob\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"rob\" \/>\n\t<meta name=\"twitter:label2\" content=\"Estimated reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"2 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/\"},\"author\":{\"name\":\"rob\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\"},\"headline\":\"Using the DTMF Decoder Module for the RC2014 from C\",\"datePublished\":\"2025-01-01T14:36:46+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/\"},\"wordCount\":273,\"image\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/assets\\\/DTMF-Decoder-Module-For-RC2014.jpg\",\"keywords\":[\"DTMF\",\"RC2014\"],\"articleSection\":[\"RC2014\"],\"inLanguage\":\"en-GB\"},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/\",\"url\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/\",\"name\":\"Using the DTMF Decoder Module for the RC2014 from C - Robert Price\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/assets\\\/DTMF-Decoder-Module-For-RC2014.jpg\",\"datePublished\":\"2025-01-01T14:36:46+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\"},\"description\":\"Using z88dk to compile C code for the RC2014 that can decode incoming tones from the DTMF Decoder Module. This uses SFRs to handle Z80 IO.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/#breadcrumb\"},\"inLanguage\":\"en-GB\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/assets\\\/DTMF-Decoder-Module-For-RC2014.jpg\",\"contentUrl\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/assets\\\/DTMF-Decoder-Module-For-RC2014.jpg\",\"width\":800,\"height\":460,\"caption\":\"DTMF Decoder module designed for the RC2014\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Using the DTMF Decoder Module for the RC2014 from C\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#website\",\"url\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/\",\"name\":\"Robert Price\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-GB\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.robertprice.co.uk\\\/robblog\\\/#\\\/schema\\\/person\\\/fac6d5b076e0e14e1fb13e15b542a6c5\",\"name\":\"rob\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-GB\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g\",\"caption\":\"rob\"}}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Using the DTMF Decoder Module for the RC2014 from C - Robert Price","description":"Using z88dk to compile C code for the RC2014 that can decode incoming tones from the DTMF Decoder Module. This uses SFRs to handle Z80 IO.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/","og_locale":"en_GB","og_type":"article","og_title":"Using the DTMF Decoder Module for the RC2014 from C - Robert Price","og_description":"Using z88dk to compile C code for the RC2014 that can decode incoming tones from the DTMF Decoder Module. This uses SFRs to handle Z80 IO.","og_url":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/","og_site_name":"Robert Price","article_published_time":"2025-01-01T14:36:46+00:00","og_image":[{"width":800,"height":460,"url":"https:\/\/www.robertprice.co.uk\/robblog\/assets\/DTMF-Decoder-Module-For-RC2014.jpg","type":"image\/jpeg"}],"author":"rob","twitter_card":"summary_large_image","twitter_misc":{"Written by":"rob","Estimated reading time":"2 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/#article","isPartOf":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/"},"author":{"name":"rob","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5"},"headline":"Using the DTMF Decoder Module for the RC2014 from C","datePublished":"2025-01-01T14:36:46+00:00","mainEntityOfPage":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/"},"wordCount":273,"image":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/#primaryimage"},"thumbnailUrl":"https:\/\/www.robertprice.co.uk\/robblog\/assets\/DTMF-Decoder-Module-For-RC2014.jpg","keywords":["DTMF","RC2014"],"articleSection":["RC2014"],"inLanguage":"en-GB"},{"@type":"WebPage","@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/","url":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/","name":"Using the DTMF Decoder Module for the RC2014 from C - Robert Price","isPartOf":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/#primaryimage"},"image":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/#primaryimage"},"thumbnailUrl":"https:\/\/www.robertprice.co.uk\/robblog\/assets\/DTMF-Decoder-Module-For-RC2014.jpg","datePublished":"2025-01-01T14:36:46+00:00","author":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5"},"description":"Using z88dk to compile C code for the RC2014 that can decode incoming tones from the DTMF Decoder Module. This uses SFRs to handle Z80 IO.","breadcrumb":{"@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/#breadcrumb"},"inLanguage":"en-GB","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/"]}]},{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/#primaryimage","url":"https:\/\/www.robertprice.co.uk\/robblog\/assets\/DTMF-Decoder-Module-For-RC2014.jpg","contentUrl":"https:\/\/www.robertprice.co.uk\/robblog\/assets\/DTMF-Decoder-Module-For-RC2014.jpg","width":800,"height":460,"caption":"DTMF Decoder module designed for the RC2014"},{"@type":"BreadcrumbList","@id":"https:\/\/www.robertprice.co.uk\/robblog\/using-the-dtmf-decoder-module-for-the-rc2014-from-c\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.robertprice.co.uk\/robblog\/"},{"@type":"ListItem","position":2,"name":"Using the DTMF Decoder Module for the RC2014 from C"}]},{"@type":"WebSite","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#website","url":"https:\/\/www.robertprice.co.uk\/robblog\/","name":"Robert Price","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.robertprice.co.uk\/robblog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-GB"},{"@type":"Person","@id":"https:\/\/www.robertprice.co.uk\/robblog\/#\/schema\/person\/fac6d5b076e0e14e1fb13e15b542a6c5","name":"rob","image":{"@type":"ImageObject","inLanguage":"en-GB","@id":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6f0eb511179100a4e968abc70403e33686e6ab3e992e392bedd2ccac01da666c?s=96&d=mm&r=g","caption":"rob"}}]}},"_links":{"self":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts\/2977","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/comments?post=2977"}],"version-history":[{"count":1,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts\/2977\/revisions"}],"predecessor-version":[{"id":2979,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/posts\/2977\/revisions\/2979"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/media\/2971"}],"wp:attachment":[{"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/media?parent=2977"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/categories?post=2977"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.robertprice.co.uk\/robblog\/wp-json\/wp\/v2\/tags?post=2977"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}