
{"id":248,"date":"2015-08-14T14:31:31","date_gmt":"2015-08-14T14:31:31","guid":{"rendered":"http:\/\/timallen.name\/?p=248"},"modified":"2015-08-14T21:12:40","modified_gmt":"2015-08-14T21:12:40","slug":"beacons-using-a-pic10f200","status":"publish","type":"post","link":"https:\/\/timallen.name\/index.php\/2015\/08\/14\/beacons-using-a-pic10f200\/","title":{"rendered":"Beacons using a PIC10F200"},"content":{"rendered":"<p>Before there were standards like iBeacon and Eddystone we had to &#8220;roll our own.&#8221; This is a primitive beacon using a PIC10F200 (8pin DIP) along with a simple 315MHz OOK transmitter. Later versions, not shown here, use SDR.<\/p>\n<h2>beacon.asm<\/h2>\n<p>This is written in PIC assembly. It simply transmits my FCC Call sign with a number tacked on the end. Production versions would substitute a UUID and checksum in place of my Call sign. The signal is intentionally weak, we only want to know if the watch (wearable device) is within a few meters. Battery life is important too, this thing should be good for about 57 years on a couple AAA batteries.<\/p>\n<p>The gist of what this code does is to set a timer and go to sleep. When the timer expires the chip wakes up and increments some counter (the timer durations are rather short) and we need some randomization to minimize the possibility of interference betwixt proximal beacons*. If it&#8217;s time to send a burst, my Call sign, then it does so, resets the counter and timer and goes back to sleep. The idea is to spend as much time asleep as possible to conserve batteries.<\/p>\n<p>beacon.asm<\/p>\n<pre class=\"lang:asm decode:true \" title=\"beacon.asm\" >\r\n; FILE: beacon.asm\r\n; AUTH: Tim Allen\r\n; DATE: 1.0 - 18 April `11\r\n; DESC: Controls a 315MHz radio, sends a \r\n;\tserial number periodically (~30s)\r\n; NOTE: Tested on PIC10F200\r\n\r\n\tinclude &lt;p10f200.inc&gt;\r\n\tlist\tp=10F200\r\n\tradix\thex\r\n\t__config _WDT_ON\r\n\r\n;----------------------------------------------------------------------\r\n;\tmacro(s)\r\n\r\nxmit\tmacro\tr0\r\n\tcall\ttxstart\r\n\tmovlw\tr0\r\n\tcall\ttxhex\r\n\tcall\ttxstop\r\n\tendm\r\n;----------------------------------------------------------------------\r\n; ram \"variables\"\r\ncblock\t0x10\r\n warmcnt\t; counter for radio warm-up\r\n count0\t\t; counter for main prog\r\n txcount\t; counter for tx0 and tx1\r\n hex\t\t; scratch for txhex\r\n xmitcnt\t; bit counter for txhex\r\n lfsr\t\t; pseudo-random number\r\nendc\r\n;----------------------------------------------------------------------\r\n\r\n\torg\t0x000\r\n\tgoto\tmain\r\n\r\nmain\t;code start\t\r\n\tmovlw\tb'11001111'\t; set watchdog post-scaler\r\n\toption\r\n\tmovlw\tb'11111000'\t; 0,1,&amp; 2 output\r\n\ttris\tGPIO\t\t; set GPIO I\/O \r\n\tbtfss\tSTATUS,NOT_PD\r\n\tgoto \trun\r\n\r\n;----------------------------------------------------------------------\r\npowerup\t; initialize things\r\n\tclrwdt\t\t\t; clear watchdog timer\r\n\r\n\tmovlw\tb'00000000'\r\n\tmovwf\tGPIO\t\t; turn GPIOs off\r\n\r\n\tmovlw\t0x05\r\n\tmovwf\tcount0\t\t; initialize the counter\r\n\tgoto\tburst\t\t; send an initial burst\r\n\r\n;----------------------------------------------------------------------\r\nrun\t; is it time for a burst?\r\n\tdecfsz\tcount0,F\r\n\tsleep\t\t\t; no go back to sleep\r\n\r\n\t; generate a pseudo-random number\r\n\tbcf\tSTATUS,C\r\n\trrf\tlfsr,W\r\n\tbtfsc\tSTATUS,C\r\n\txorlw\t0xb4\r\n\tmovwf\tlfsr\r\n\tandlw\t0x03\t\t; limit the random to 0-3\r\n\tmovwf\tcount0\t\t; set the counter\r\n\tincf\tcount0,F\t; just make sure it's not 0\r\n\r\nburst\t; send a beacon string\r\n\tbsf\tGPIO,2\t\t; power-up the radio\r\n\tmovlw\t0xff\r\n\tmovwf\twarmcnt\r\nwarmlp\tdecfsz\twarmcnt,F\t; give it a sec\r\n\tgoto\twarmlp\r\n\r\n\txmit\t'K'\r\n\txmit\t'G'\r\n\txmit \t'4'\r\n\txmit\t'E'\r\n\txmit\t'U'\r\n\txmit\t'K'\r\n\txmit\t'0'\r\n\txmit\t'0'\r\n\txmit\t0xf5\r\n\r\n\tbcf\tGPIO,2\t\t; power-down the radio\r\n\tsleep\t\t\t; go back to sleep\r\n\r\ntxstart\t; transmit a start\r\n\tbsf\tGPIO,0\t\t; trigger the scope\r\n\tcall\ttx0\r\n\tretlw\t0x00\r\n\r\ntxstop\t; transmit a stop\r\n\tcall\ttx1\r\n\tbcf\tGPIO,0\t\t; un-trigger the scope\r\n\tretlw\t0x00\r\n\r\ntx1\t; transmit a 1 bit subroutine\r\n\tbcf\tGPIO,1\r\n\tmovlw\td'185'\r\n\tmovwf\ttxcount\r\ntx1lp\tnop\r\n\tdecfsz\ttxcount,F\r\n\tgoto\ttx1lp\r\n\tretlw\t0x00\r\n\r\ntx0\t; transmit a 0 bit subroutine\r\n\tbsf\tGPIO,1\r\n\tmovlw\td'180'\r\n\tmovwf\ttxcount\r\ntx0lp\tnop\r\n\tdecfsz\ttxcount,F\r\n\tgoto\ttx0lp\r\n\tretlw\t0x00\r\n\r\ntxhex\t; transmit a hex\r\n\tmovwf\thex\r\n\tmovlw\t0x08\t\t; set the counter\r\n\tmovwf\txmitcnt\r\nnxtop\trrf\thex,F\r\n\tbtfsc\tSTATUS,C\r\n\tgoto\tx1\r\n\tcall\ttx0\t\t; zero\r\n\tgoto \tnxbtm\r\nx1\tcall\ttx1\t\t; one\r\nnxbtm\tdecfsz\txmitcnt,F\r\n\tgoto\tnxtop\r\n\tretlw\t0x00\r\n\r\n\tend\r\n<\/pre>\n<p>Makefile<\/p>\n<pre class=\"lang:default decode:true \" >\r\nbeacon.hex: beacon.asm\r\n\tgpasm beacon.asm\r\n\r\nburn:\r\n\tpk2cmd -PPIC10F200 -J -R -F beacon.hex -M\r\n\r\nclean:\r\n\trm *.hex *.lst *.cod\r\n<\/pre>\n<p>* This is a bit tough to explain so bare with me. The oscillators on these things are not precise. So imagine we were to send a burst every 30 wake-ups (e.g. no randomization). Okay so lets say you have two of these close together and we put batteries in them at the same time. Now every 30 wake-ups they both wake up and clobber each other (the wearable can&#8217;t hear either because they &#8220;talk&#8221; over each other). Now eventually, because the oscillators are imprecise, they drift apart but that may take hours; therefore, we introduce some randomization to keep them asynchronous. I&#8217;m skipping some nuance here but I hope you get the idea.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Before there were standards like iBeacon and Eddystone we had to &#8220;roll our own.&#8221; This is a primitive beacon using a PIC10F200 (8pin DIP) along with a simple 315MHz OOK transmitter. Later versions, not shown here, use SDR. beacon.asm This is written in PIC assembly. It simply transmits my FCC Call sign with a number &hellip; <a href=\"https:\/\/timallen.name\/index.php\/2015\/08\/14\/beacons-using-a-pic10f200\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Beacons using a PIC10F200<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8,5],"tags":[],"class_list":["post-248","post","type-post","status-publish","format-standard","hentry","category-embedded","category-medicaldevice"],"_links":{"self":[{"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/posts\/248","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/comments?post=248"}],"version-history":[{"count":8,"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/posts\/248\/revisions"}],"predecessor-version":[{"id":257,"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/posts\/248\/revisions\/257"}],"wp:attachment":[{"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/media?parent=248"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/categories?post=248"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/timallen.name\/index.php\/wp-json\/wp\/v2\/tags?post=248"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}