tag:blogger.com,1999:blog-12139700750097895552024-02-21T17:56:58.293+08:00Dr MartyThoughts on Digital Electronics, Embedded Systems Design, FPGAs, and the odd personal ideas.Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.comBlogger34125tag:blogger.com,1999:blog-1213970075009789555.post-25855781120957026732020-05-12T18:09:00.000+08:002020-05-12T18:09:23.851+08:00Ring Buffers<div><span style="font-family: verdana, sans-serif;">Source code: <a href="https://github.com/DrMarty/STM32Utils/tree/master/UartIO" target="_blank">https://github.com/DrMarty/STM32Utils/tree/master/UartIO</a></span></div><div><br /></div><span style="font-family: verdana, sans-serif;">In my earlier post about <a href="http://drmarty.blogspot.com/2020/05/implementing-printf-on-uart.html#links">redirecting printf() to a UART</a>, I mentioned that the implementation was 'blocking'. This means that the calling code has to wait for all the data to be printed out the serial port before it can continue. If, for example, you are sending out a modest string of 20 characters at 115,200 baud, your code will be sitting idle for around 1.7ms, and at 100MHz clock speed, that translates to around 173,000 (single-cycle) instructions that could have done something productive in the meantime.</span><br />
<span style="font-family: verdana, sans-serif;">What you really want is to hand the character processing off to a background routine so your mainline code can execute as quickly as possible. One very effective way to do this is to implement a ring buffer.</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZWahGo7Cl4VUdFkMdpH7SspMK2rXlAZLVBsLbpMa5WMfVXPHXWMDYci-B77CFukatIg2z4pk0dv2ly4tNCg1YXKZwBTAm7h5pd4wAsl55M6YrGDc8E5DoWjjVYObAkctKnswuooJyjN0t/s1600/RingBuff1.png" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="800" data-original-width="728" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhZWahGo7Cl4VUdFkMdpH7SspMK2rXlAZLVBsLbpMa5WMfVXPHXWMDYci-B77CFukatIg2z4pk0dv2ly4tNCg1YXKZwBTAm7h5pd4wAsl55M6YrGDc8E5DoWjjVYObAkctKnswuooJyjN0t/s320/RingBuff1.png" width="291" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">Imagine an array of 16 characters and two indexes:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">#define TX_BUFF_SZ 16</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">char TxBuffer[TX_BUFF_SZ];</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">int InsertIDX = 0;</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">int ExtractIDX = 0;</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">When we want to write data into the buffer, we use the </span><span style="font-family: "courier new", courier, monospace;">InsertIDX</span><span style="font-family: verdana, sans-serif;"> to write into the next available slot, and then increment the index;</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">TxBuffer[InsertIDX++] = write_ch;</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">And when </span><span style="font-family: "courier new", courier, monospace;">InsertIDX</span><span style="font-family: verdana, sans-serif;"> gets to the end of the buffer, we wrap it back to zero as follows:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">If (InsertIDX >= TX_BUFF_SZ)</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">InsertIDX = 0;</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">This code works in the generic case, but if you initially set your buffer size to a power of 2, you can get a little fancy by logically AND'ing </span><span style="font-family: "courier new", courier, monospace;">InsertIDX</span><span style="font-family: verdana, sans-serif;"> to mask off the high-order bits.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">InsertIDX &= (TX_BUFF_SZ - 1);</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">Putting it all together, we can create a generic ring-buffer write function that also enables a transmitter empty interrupt as follows:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">void rb_putchar(char ch)</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">{</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;"> TxBuffer[InsertIDX++] = ch;</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;"> InsertIDX &= (TX_BUFF_SZ - 1);</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;"> TxEmptyInterruptEnable = 1; //Enable the TxEmpty interrupt</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">}</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">So long as TxBuffer is at least as large as the largest amount of data we might want to send out in a single </span><span style="font-family: "courier new", courier, monospace;">printf()</span><span style="font-family: verdana, sans-serif;"> call, the above code will allow us to buffer the data and return control back to the calling routine as quickly as possible - i.e. it is no longer 'blocking'.</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">Now let's deal with feeding each character one-by-one to the USART. This would be done inside an TxEmpty interrupt service routine (ISR). Observe that when </span><span style="font-family: "courier new", courier, monospace;">ExtractIDX</span><span style="font-family: verdana, sans-serif;"> catches up to </span><span style="font-family: "courier new", courier, monospace;">InsertIDX</span><span style="font-family: verdana, sans-serif;"> there is no more data in the ring buffer to send out so we need to disable further TxEmpty interrupts:</span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><br /></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: "courier new", courier, monospace;">void ISR_TxEmpty(void)</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new", courier, monospace;">{</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new", courier, monospace;"> UartTX = TxBuffer[ExtractIDX++];</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new", courier, monospace;"> ExtractIDX &=(TX_BUFF_SZ - 1);</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new", courier, monospace;"> if (ExtractIDX == InsertIDX)</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new", courier, monospace;"> TxEmptyInterruptEnable = 0; //Disable further TX empty interrupts</span></div>
<div class="separator" style="clear: both;">
<span style="font-family: "courier new", courier, monospace;">}</span></div>
<h4 style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;">Caveats</span></h4>
<div>
<span style="font-family: verdana, sans-serif;">To help keep the focus on the core concepts, </span><span style="font-family: verdana, sans-serif;">I've kept the code above very simply</span><span style="font-family: verdana, sans-serif;">, but in practice, you'll need to qualify your declarations of </span><span style="font-family: "courier new", courier, monospace;">InsertIDX</span><span style="font-family: verdana, sans-serif;"> and </span><span style="font-family: "courier new", courier, monospace;">ExtractIDX</span><span style="font-family: verdana, sans-serif;"> as volatile so that the compiler recognizes these variables can be updated outside of the normal function execution path.</span></div>
<div><br /></div>
Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-25768667704304013732020-05-11T16:47:00.007+08:002020-05-12T18:17:50.445+08:00stdio - to buffer or not to buffer?<div>
<span style="font-family: verdana, sans-serif;"
><font size="2"
>Source code: <a
href="https://github.com/DrMarty/STM32Utils/tree/master/UartIO"
style="color: #4d469c; text-decoration-line: none;"
target="_blank"
>https://github.com/DrMarty/STM32Utils/tree/master/UartIO</a
></font
></span
>
</div>
<div>
<font size="2"
><br
style="background-color: white; color: #444444; font-family: arial, tahoma, helvetica, freesans, sans-serif;"
/></font>
</div>
<font size="2"
><span style="font-family: verdana, sans-serif;"
>In my previous post, I showed how stdio could be redirected to send
printf() output to an available USART. It was a basic implementation
designed to get things moving, but you may encounter a little quirk when
sending strings that don't end with a newline '\n' character.</span
><br />
<span style="font-family: verdana, sans-serif;"
>By default, stdio buffers (holds onto) outgoing data until it sees a
newline character; at which point it sends the entire line (to the serial
port). The benefit of this is that it reduces the amount of low level
interactions you need to have with the USART driver code, but the
disadvantage is that you have to ensure each printf() call ends with a
newline if you want the string to be immediately presented to the COM
port.</span
><br />
<span style="font-family: verdana, sans-serif;"
>I'll leave it up to you as to which implementation is best for your
situation, but in case you decide to eliminate the input and output
buffering, here's how to do it in C.</span
><br />
<span style="font-family: verdana, sans-serif;"
>Somewhere in your initialization code, add the following lines:</span
><span style="font-family: verdana, sans-serif;"><br /></span>
</font>
<pre
style="text-align: left;"
><font size="2"><span style="font-family: "courier new", courier, monospace;">setbuf(stdout, NULL);<br /></span></font><font size="2"><span style="font-family: "courier new", courier, monospace;">setbuf(stderr, NULL);<br /></span></font><font size="2"><span style="font-family: "courier new", courier, monospace;">setvbuf(stdin, NULL, _IONBF, 0);</span></font></pre>
<font size="2"
><span style="font-family: verdana, sans-serif;"
>The first line will remove buffering from stdout (which is where printf()
goes by default)</span
><br />
<span style="font-family: verdana, sans-serif;"
>The second line will remove buffering from stderr (if you are using that
for directing error information)</span
><br />
<span style="font-family: verdana, sans-serif;"
>The last line will remove buffering from stdin - which is the default for
where scanf() will look for input.</span
><br />
<span style="font-family: verdana, sans-serif;"><br /></span>
<span style="font-family: verdana, sans-serif;"
>The juicy details can be found here:</span
><br />
<a
href="https://www.gnu.org/software/libc/manual/html_node/Controlling-Buffering.html"
><font face="verdana"
>https://www.gnu.org/software/libc/manual/html_node/Controlling-Buffering.html</font
></a
><br />
<span style="font-family: verdana, sans-serif;"><br /></span
></font>
<br />
Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com3tag:blogger.com,1999:blog-1213970075009789555.post-2382525652841250502020-05-05T11:04:00.007+08:002020-05-12T18:27:49.352+08:00Implementing printf() on a UART<font size="2"><span style="font-family: verdana, sans-serif;">When developing on a new embedded (bare metal) platform, one of the first things I look for (after getting an LED to flash) is the ability to output text to a display. Usually the simplest path is to commandeer one of the UARTs and to start bashing characters out the TX pin and receiving them at the host end through a PuTTY terminal. So how to implement this efficiently?</span><br />
<span style="font-family: verdana, sans-serif;"><br /></span>
<span style="font-family: verdana, sans-serif;">The first question you'll need to resolve is how to get characters from your code into the UART. Hopefully the frawework you are using provides a simple setup process and wrapper to allow you to initialize the UART and send a single character. In the STM32CubeIDE environment, the UART properties can be setup fairly simply:</span><br />
</font><div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYwOk2fPIGujgb97HLfjOE79YaBcbETV7t7H0wMUNgANyl57vGX7GRbuONmSKXZ5mZmk20Q_Z07FWN_ip81U1cFM2wgPnO-o0gpv5SG8OwAB7YpmGfv2BJH_ryPIqbJv0B7DEhjRmwtn56/s1600/UART+Settings+1.png" style="margin-left: 1em; margin-right: 1em;"><font size="2"><img border="0" data-original-height="958" data-original-width="833" height="640" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYwOk2fPIGujgb97HLfjOE79YaBcbETV7t7H0wMUNgANyl57vGX7GRbuONmSKXZ5mZmk20Q_Z07FWN_ip81U1cFM2wgPnO-o0gpv5SG8OwAB7YpmGfv2BJH_ryPIqbJv0B7DEhjRmwtn56/s640/UART+Settings+1.png" width="555" /></font></a></div>
<div class="separator" style="clear: both; text-align: center;">
</div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><font size="2"><br /></font></span></div>
<div class="separator" style="clear: both; text-align: left;">
<font size="2"><span style="font-family: verdana, sans-serif;">115200 is a pretty safe baud rate to start with. I've also shown the corresponding PuTTY settings too. Once you've proved that basic communications are working, you will probably be able to set the baud rate much higher; although take care when doing this. Even though the STM32 might be able to do 8Mbaud, FTDI-based USB Serial devices will top out at 3Mbaud: (</span><a href="https://www.ftdichip.com/Support/Knowledgebase/index.html?whatbaudratesareachieveabl.htm"><span style="font-family: Verdana, sans-serif;">https://www.ftdichip.com/Support/Knowledgebase/index.html?whatbaudratesareachieveabl.htm</span></a>)</font></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><font size="2">In any case, let's assume you've correctly setup the comms basics (don't forget to make sure the parity and stop bits match). Next job is to send something simple.</font></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><font size="2"><br /></font></span></div>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><font size="2">Once again, using the STM32CubeIDE environment as an example, ST offers a simple function call as part of the HAL (Hardware Abstraction Layer) interface:</font></span></div>
<pre style="clear: both; text-align: left;"><span style="font-family: "courier new", courier, monospace;"><font size="2">HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)</font></span></pre>
<div class="separator" style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><font size="2">Assuming STM32CubeIDE has instantiated the UART handle as "huart1", you can make a simple call from your code like this:</font></span></div>
<pre style="clear: both; text-align: left;"><span style="font-family: "courier new", courier, monospace;"><font size="2">char msg[] = "Hello World";<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2">hres = HAL_UART_Transmit(huart1, msg, strlen(msg), 100);</font></span></pre>
<h3 style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><font size="2">Tying into printf()</font></span></h3>
<div class="separator" style="clear: both; text-align: left;">
<font size="2"><span style="font-family: verdana, sans-serif;">Sending out "Hello World" might be initially very gratifying, but eventually you'll need to send out more advanced information such as variable values. One tempting option is to jump in and write your own </span><span style="font-family: "courier new", courier, monospace;">MyPrintf()</span><span style="font-family: verdana, sans-serif;"> function, but that would involve a whole lot of re-inventing the wheel. A much better option is to tie into the existing functionality that already exists. Fortunately, the authors of most embedded frameworks understand that developers will want to redirect their output through various peripherals so they provide the infrastructure to readily support it.</span></font></div>
<div class="separator" style="clear: both; text-align: left;">
<font size="2"><span style="font-family: verdana, sans-serif;">If you dig deep enough, you'll find that after several layers of code, the standard </span><span style="font-size: x-small;"><span style="font-family: "courier new", courier, monospace;">printf()</span></span><span style="font-family: verdana, sans-serif;"> function distills down to one or two low-level functions. Take a look in the syscalls.c file for the </span><span style="font-size: x-small;"><span style="font-family: "courier new", courier, monospace;">_write()</span></span><span style="font-family: verdana, sans-serif;"> function:</span></font></div>
<pre style="clear: both; text-align: left;"><span style="font-family: "courier new", courier, monospace;"><font size="2">__attribute__((weak)) int _write(int file, char *ptr, int len)<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2">{<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>int DataIdx;</font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>for (DataIdx = 0; DataIdx < len; DataIdx++)<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>{<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>__io_putchar(*ptr++);<br /></font></span><span style="font-family: "courier new", courier, monospace; font-size: xx-small;"><font size="2"><span style="white-space: pre;"> </span>}<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>return len;<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2">}</font></span></pre>
<div class="separator" style="clear: both; text-align: left;">
</div>
<div style="text-align: left;"><span style="font-family: verdana, sans-serif;">Take note that this function is prefaced by </span><span style="font-family: "courier new", courier, monospace;">__attribute__((weak))</span><span style="font-family: verdana, sans-serif;">. This is a message to the compiler to look elsewhere in the code for a </span><span style="font-size: small;"><span style="font-family: "courier new", courier, monospace;">_write()</span></span><span style="font-family: verdana, sans-serif; font-size: small;"> function and use that one first, but if it can't find one then use this one. In effect, it allows you to implement your own </span><span style="font-family: "courier new", courier, monospace;">_write()</span><span style="font-family: verdana, sans-serif;"> function within your codebase without needing to modify the library source files. A UART-based implementation would therefore be:</span></div>
<pre style="clear: both; text-align: left;"><span style="font-family: "courier new", courier, monospace;"><font size="2">int _write(int file, char *ptr, int len)<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2">{<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>HAL_StatusTypeDef hres;<br /></font></span><span style="font-family: "courier new", courier, monospace; font-size: xx-small;"><font size="2"><span style="white-space: pre;"> </span>hres = HAL_UART_Transmit(huart1, (uint8_t*)ptr, len, TX_BLOCKING_TIMEOUT);<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>if (hres == HAL_OK)<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>return len;<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>else<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2"><span style="white-space: pre;"> </span>return -1;<br /></font></span><span style="font-family: "courier new", courier, monospace;"><font size="2">}</font></span></pre>
<div class="separator" style="clear: both; text-align: left;">
<font size="2"><span style="font-family: verdana, sans-serif;">With this function now in your code, you can access all of the wonderful formatting capabilities that come with </span><span style="font-family: "courier new", courier, monospace;">printf()</span><span style="font-family: verdana, sans-serif;"> and your output will be magically directed to the serial port.</span></font></div>
<h3 style="clear: both; text-align: left;">
<span style="font-family: verdana, sans-serif;"><font size="2">Concluding Remarks</font></span></h3>
<div class="separator" style="clear: both; text-align: left;">
<font size="2"><span style="font-family: verdana, sans-serif;">The implementation above gets you up and running with basic character output capabilities but there's a hidden problem you may face further down the track. This implementation is 'blocking'; which means that it waits until all characters have been successfully piped out the serial port before it returns control back to the calling function. In timing critical applications or when sending large volumes of data, this could have an impact on the performance of your system, so i</span><span style="font-family: verdana, sans-serif;">n another blog entry, I'll talk about how to implement a ring-buffer and interrupts so your code doesn't have to wait around for the UART to finish its thing.</span></font></div><div class="separator" style="clear: both; text-align: left;"><br /></div><div class="separator" style="clear: both; text-align: left;"><font face="verdana, sans-serif" size="2">Source code: <a href="https://github.com/DrMarty/STM32Utils/tree/master/UartIO" target="_blank">https://github.com/DrMarty/STM32Utils/tree/master/UartIO</a></font></div><div class="separator" style="clear: both; text-align: left;"><font face="verdana, sans-serif" size="2"><br /></font></div>
Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-26538837810697196272020-04-29T19:10:00.001+08:002020-05-05T09:08:32.521+08:00fopen() - Text or Binary?<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Its often convenient to control an embedded system remotely via some sort of communications protocol. In the good ole days, I'd devise some sort of homebrew communications protocol that was specific to my application's needs and I'd bash some data in and out of the serial port. Having grown up on 8-bit micros with limited RAM, every byte was valuable so there was a strong inclination to pack things tightly into binary streams, but the problem with that is how to test it... and before you know it I'm being drag into an endless rabbit hole of development on the PC side just so I could conveniently communicate with the embedded app.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Embedded processors have come a long way and right now, I'm getting up close and personal with some pretty nifty STM32 processor boards - this one in particular that I sourced from Banggood: <a href="https://sea.banggood.com/STM32F407VET6-Development-Board-Cortex-M4-STM32-Small-System-ARM-Learning-Core-Module-p-1460490.html">https://sea.banggood.com/STM32F407VET6-Development-Board-Cortex-M4-STM32-Small-System-ARM-Learning-Core-Module-p-1460490.html</a></span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijUEhbcnmKs4GNsoel1Hm7zUqf4ECiuKc6DREIV5Tz44Y-trGOrLcMPPhyphenhyphen9Dz2dJ28Nk-R5COipcNCWkaZJdMbAwLrxumz1PvvRN4qe4Q1TEykyjhgvMcQU-p4vOmlClpwgbHowNhaUwBC/s1600/STM32F407VET6+img2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "verdana" , sans-serif; font-size: x-small;"><img border="0" data-original-height="873" data-original-width="1036" height="269" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEijUEhbcnmKs4GNsoel1Hm7zUqf4ECiuKc6DREIV5Tz44Y-trGOrLcMPPhyphenhyphen9Dz2dJ28Nk-R5COipcNCWkaZJdMbAwLrxumz1PvvRN4qe4Q1TEykyjhgvMcQU-p4vOmlClpwgbHowNhaUwBC/s320/STM32F407VET6+img2.png" width="320" /></span></a></div>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Compared with an 8051, these ARM devices are a beast; and the development boards are so cheap! It's time to cast off the constraints of decades past and update my comms routines... enter JSON.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">JSON is sooo simple even I can wrap my head around it; it's text based which means testing it with my embedded app is simply a case of sending text files through a PuTTY terminal. Furthermore, because JSON is used so widely across the winternet, I'm pretty confident I'll be able to keep using it even if I upgrade my comms to Etherweb.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">I dug around and quickly settled on a relatively compact JSON interpreter (called JSMN) from Serge Zaitsev (kudos <a href="https://twitter.com/zsergo">@zsergo</a>): <a href="https://zserge.com/jsmn/">https://zserge.com/jsmn/</a>. It comes packaged as a single C header file which feels a little hacky but its nonetheless effective and I was able to get a basic command interpreter up and running on my target board pretty quickly.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">At that point, I started thinking more about what sort of commands I might want to exchange and it became pretty clear that I was going to need some sort of generic command interpreter that was easy to abstract and extend. That's going to be a work in progress but the relevance to today's discussion is how it drove me back to establishing a parallel development platform that would allow me to develop and test code on my PC rather than needing to run everything from my target (ARM) platform, and how I bumped into a nasty little PITA on how Windows processes text files.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">I'm not going to post my original code because some dufuss will blindly cut and past it into their application and wonder why it doesn't work.. instead I'll post the working code:</span><br />
<br />
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> ============================================================================</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Name : main.c</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Author : Marty Hauff</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Version :</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Copyright : Use at own risk</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> Description : Test scaffold for reading a file and processing...</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> ============================================================================</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> */</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">#include <stdio.h></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">#include <stdlib.h></span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">#include <limits.h><span style="white-space: pre;"> </span>//PATH_MAX</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">#include <unistd.h><span style="white-space: pre;"> </span>//getcwd()</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">#include <sys/stat.h><span style="white-space: pre;"> </span>//struct stat</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">#include <string.h><span style="white-space: pre;"> </span>//strlen()</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">#define MAX_TOKENS 256</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">int main(void) {</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>FILE* fp;</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>char* Filename;</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>struct stat st;</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>char cwd[PATH_MAX];</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>char* json_string = {0};</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white;"><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small; white-space: pre;"> </span><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">printf ("\nJSON Test\n");</span></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>getcwd(cwd, sizeof(cwd));</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>if (cwd != NULL) {</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("Current working dir: %s", cwd);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>} else {</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>perror("getcwd() error");</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>return EXIT_FAILURE;</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>}</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>Filename = "JSON Examples/JSON_2.json";</span></div>
<div style="text-align: left;">
<span style="background-color: white;"><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small; white-space: pre;"> </span><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">fp = fopen(Filename, "rb");</span><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small; white-space: pre;"> </span><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">//MUST use binary mode otherwise \r\n sequences get messed up!!</span></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>if (fp == NULL)</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>{</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("\nFailed to open %s", Filename);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>return EXIT_FAILURE;</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>}</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("\n\"%s\" opened successfully", Filename);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>stat(Filename, &amp;st);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("\nStat Size: %ld", st.st_size);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>fseek(fp, 0, SEEK_END);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("\nfseek Size: %ld", ftell(fp));</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>fseek(fp, 0, SEEK_SET);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>json_string = malloc(st.st_size+1);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>fread(json_string, st.st_size, 1, fp);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>fclose(fp);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>json_string[st.st_size] = '\0';</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("\nstrlen Size: %d", strlen(json_string));</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("\n%s",json_string);</span></div>
<div style="text-align: left;">
<span style="background-color: white;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white;"><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small; white-space: pre;"> </span><span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">jsmn_parser p;</span></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>jsmntok_t tkns[MAX_TOKENS];</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>int nodes = 0;</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>jsmn_init(&amp;p);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>nodes = jsmn_parse(&amp;p, json_string, strlen(json_string), tkns, MAX_TOKENS);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>printf ("\nFound %d nodes", nodes);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><br /></span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>free(json_string);</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;"><span style="white-space: pre;"> </span>return EXIT_SUCCESS;</span></div>
<div style="text-align: left;">
<span style="background-color: white; font-family: "courier new" , "courier" , monospace; font-size: xx-small;">}</span></div>
<div>
<br /></div>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">The thing that got me stuck for a day was that pesky little 'b' character in the fopen command. Here's what the output looked like <b>without </b>it (I'm using some test JSON from: <a href="https://json.org/example.html">https://json.org/example.html</a>):</span><br />
<br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">JSON Test</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Current working dir: C:\Users\user\Documents\Projects\WinTest</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">"JSON Examples/JSON_2.json" opened successfully</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Stat Size: 253</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">fseek Size: 253</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">strlen Size: 253</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">{"menu": {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "id": "file",</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "value": "File",</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "popup": {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "menuitem": [</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> {"value": "New", "onclick": "CreateNewDoc()"},</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> {"value": "Open", "onclick": "OpenDoc()"},</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> {"value": "Close", "onclick": "CloseDoc()"}</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> ]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">}}</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">âãäåæçèéêëì</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Found -2 nodes</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">I couldn't work out what was causing the garbage at the end of the stream (second last line) and why jsmn was subsequently failing to parse the file. The clue is that there are the same number of garbage characters as there are lines in the JSON string. Take a look at a hex dump of the JSON file:</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2BFNAsO84enrzJ7hhjIy7dzhWiJ9dAHClGH6o_iwAJY09j6zwxG59htUtliZ0bY3wKdK_3giaPnrSpj1UKEjSh5LrToE_CZkHmD3rYQtbIx0jOUQ5sd1FT9SQX86ijukSFLziLrBbQsBE/s1600/JSON+as+hex+file.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="258" data-original-width="597" height="138" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh2BFNAsO84enrzJ7hhjIy7dzhWiJ9dAHClGH6o_iwAJY09j6zwxG59htUtliZ0bY3wKdK_3giaPnrSpj1UKEjSh5LrToE_CZkHmD3rYQtbIx0jOUQ5sd1FT9SQX86ijukSFLziLrBbQsBE/s320/JSON+as+hex+file.png" width="320" /></a></div>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Take note of the 0D 0A sequence. Also take a look at these settings in Notepad++</span><br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxxNBKGhnA_PZgB8QTzng0Y1W_4wKEiz-GWN8qESLf2-F3J3aGgVJwwP7M72diGaHNh0eXcbjVyJcgNht8HC8XcuJjnGhySzOHUW6gn41CXSyW8x0uy5zg8xxHURLqGmNyPGce7QhfX4gw/s1600/Notepad%252B%252B+CR+LF+options.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><span style="font-family: "verdana" , sans-serif; font-size: x-small;"><img border="0" data-original-height="394" data-original-width="849" height="185" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhxxNBKGhnA_PZgB8QTzng0Y1W_4wKEiz-GWN8qESLf2-F3J3aGgVJwwP7M72diGaHNh0eXcbjVyJcgNht8HC8XcuJjnGhySzOHUW6gn41CXSyW8x0uy5zg8xxHURLqGmNyPGce7QhfX4gw/s400/Notepad%252B%252B+CR+LF+options.png" width="400" /></span></a></div>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Without the 'b' in the fopen() call, the file is opened as a text file and Windows strips out all the CR (0x0D '\r') characters when its reading the contents into a buffer. As a result, the string stored in memory is actually shorter than the number of characters read from disk.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Now look at the output when the 'b' is included in the fopen() call (i.e. as per the code listing above):</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">JSON Test</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Current working dir: C:\Users\user\Documents\Projects\WinTest</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">"JSON Examples/JSON_2.json" opened successfully</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Stat Size: 253</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">fseek Size: 253</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">strlen Size: 253</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">{"menu": {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "id": "file",</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "value": "File",</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "popup": {</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> "menuitem": [</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> {"value": "New", "onclick": "CreateNewDoc()"},</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> {"value": "Open", "onclick": "OpenDoc()"},</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> {"value": "Close", "onclick": "CloseDoc()"}</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> ]</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;"> }</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">}}</span><br />
<span style="font-family: "courier new" , "courier" , monospace; font-size: xx-small;">Found 26 nodes</span><br />
<br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">The CR character remains in the text stream so the console output (on Eclipse) double spaces each line, but take note that we no longer get the garbage at the end of the stream; AND jsmn has managed to parse the file correctly.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Take note of the moral of the story - consider reading a file in binary mode even if you know the contents are text.</span><br />
<span style="font-family: "verdana" , sans-serif; font-size: x-small;"><br /></span>
<span style="font-family: "verdana" , sans-serif; font-size: x-small;">Now to work out how to build a generic JSON command interpreter.</span>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-37763644398277770152020-04-29T10:37:00.000+08:002020-04-29T10:37:29.876+08:00Return from hiatusAfter almost 10 years since my last blog, I've decided it's about time I started writing up a few things again. It's been an eventful 10 years... not the least of which was living in China for almost 8 of them. The great firewall of China blocks this blogger site so it was increasingly difficult to make entries and, for the most part, I was so busy doing life that finding time to update this blog just became one of those things that fell off the priority list.<br />
In any case, kids are now living their own independent lives back in Australia and a year ago wifey and I moved to Singapore and I've got a lot more control over my time. And with this Covid-19 shenanigans I've been recently put out of (working for the man) work and so I've got plenty of time to pursue some projects of my own. Over the past couple of years, I've also bought some reasonably good test equpment (DSO, PSup, Sig Gen & Desktop Multimeter) so I'm pretty well equipped to do development at home. One of these days I'll do a writeup of my lab setup.<br />
For now, this is a quick hello to the world and I hope to be keeping this site much better fed.<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaPMgS5teMGAmY7_lMW3bIffSaWE_ru-nkQ5Imc2aq5rBFjUQH5C8Vdx-qbxUApQGJE7jAw0ycIUbtYnTUQvCI9G_O5D3EWeY-Cs3CJD4_l4Ss1Y2X5zaOVo48g5y0eZ0C45ZNt35M7hs4/s1600/Marty+Mt+Wellington%252C+Hobart+24-Dec-2019.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" data-original-height="908" data-original-width="1600" height="181" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjaPMgS5teMGAmY7_lMW3bIffSaWE_ru-nkQ5Imc2aq5rBFjUQH5C8Vdx-qbxUApQGJE7jAw0ycIUbtYnTUQvCI9G_O5D3EWeY-Cs3CJD4_l4Ss1Y2X5zaOVo48g5y0eZ0C45ZNt35M7hs4/s320/Marty+Mt+Wellington%252C+Hobart+24-Dec-2019.jpg" width="320" /></a></div>
<br />Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-67399612255421735252011-04-15T06:52:00.003+08:002011-04-15T07:01:09.965+08:00Using Competitors as SuppliersNot that long ago, a PCB designer posted an interesting <a href="http://www.linkedin.com/groupItem?view=&gid=1821753&type=member&item=42533727&qid=6088f28f-99c0-49bf-b16a-75e5cb513359&goback=%2Egde_1821753_member_42533727%2Egmp_1821753">question</a> on one of the <a href="http://www.linkedin.com/">LinkedIn</a> discussion groups. The question was this: <div><br /></div><div>"How do you feel about using a fabricator that also offers design services?"<div><br /></div><div>I responded to the discussion directly but for the benefit of those who may not be members of the group, I wanted to share my thoughts more broadly because it shows how building connected devices can actually help defend against suppliers who might also be competitors.</div><div><div><br /></div><div>It's a really interesting question that you are posing but I think it points to a bigger issue.<br />I use a mechanic in my local area to service my car. The service he offers (in terms of tuning my car up and changing the oil) can not be differentiated from any other mechanic I might choose to use, but over time, I have become loyal to this one mechanic because the service he offers goes beyond the oil he puts in my car. Sitting at the back of our transactions is a relationship and the history of that relationship is not something that a competitor could replace by simply undercutting the price.<br />So when it comes to creating an electronics product, I think designers really need to ask themselves whether the sole basis of their business is built on the secret sauce they add to their boards in the form of IP, or does it extend to an ongoing relationship.<br />I know the Apple example is overused but it really highlights the point. They don't make the cheapest MP3 players, but they have changed the game so that it's actually not an MP3 player that I'm buying from Apple; its a relationship and ability to seamlessly connect into their eco-system of content. In effect, the player is almost ancillary to my real requirement which is to have good quality music / entertainment on the run.<br />So the best defence against would-be IP thieves is to build products that develop an ongoing relationship and provide a reason for customers to remain connected to you... and then service those customers as if your life depended on it (because it does)!</div></div></div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-2525557284968087142011-04-13T20:15:00.000+08:002011-04-13T20:14:02.979+08:00China, here we comeIt seems ironic that my last post dealt with the issues that foreigners have in grasping command of the English language. And now, it seems, I am to become a foreigner too.<div>I haven't been on the air much over the past 6 months because I've been backwards and forwards to China several times while working pretty solidly on the launch of a brand new training facility at our office in Shanghai. I'm thrilled with what has come together around that project and the fact that this week marks the launch of our first public course.</div><div>While "paid for" training might be a relatively new thing in China, the appetite is very high for quality courses that lift designers to a new level of skill and provide them with a deeper understanding of the methodology driving the creation of Altium's solutions. Our new facility will allow us to help customers better than ever before while also feeding the huge demand for skilled electronics designers as China continues on its massive growth surge.</div><div><br /></div><div>In other news, you no doubt would have read the <a href="http://altium.com/files/corp/investor/pdfs/Altium_to_relocate_its_global_HQ_to_China.pdf">news</a> that Altium is relocating its headquarters to Shanghai, China. This has been met with a huge range of responses from customers and industry commentators. Some have suggested that it makes perfect logical sense given the huge investment being made in China in technology areas that are in absolute alignment with Altium's vision to create a "copper to cloud" design tool. But others have been slightly less rational. At the extreme end they've insinuated that Altium's move can only mean that we have lost our way and have been hijacked by Communist antagonists who are planning on overthrowing Western military installations by using Altium Designer as a back door window into the inner sanctums of top-secret design houses.</div><div>In all honesty, I've got little time for xenophobic tirades but I do understand the depth of emotion that news such as this can evoke. It is very hard for designers in the West to not feel threatened by Altium's decision. Western designers have been the fortunate benefactors of over a century of manufacturing fueled growth that has led to great relative prosperity. But Altium's decision to locate its headquarters in Shanghai rather than Silicon Valley makes a very strong statement about where it sees the next wave of prosperity coming from. And that statement challenges several assumptions that many in the West have become accustomed to making. But on reflection, do we really believe that the West has some sort of monopoly on innovative design and quality? Do we really believe that our political system somehow gives us the absolute right to create better products?</div><div>Now before anyone starts sending volleys of political abuse at me, please take a moment to consider what I'm saying. The way I see it is this: when 1.4 billion people start becoming upwardly mobile, you can choose to stand at the shore and yell at the encroaching tide. Or you can jump right in and ride the wave of your life.</div><div>I, for one, am a surfer and my family and I are currently preparing for a move to China.</div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com1tag:blogger.com,1999:blog-1213970075009789555.post-6601853673697364352010-09-21T10:22:00.005+08:002010-09-21T12:13:06.013+08:00Thank goodness English is hard to masterI took a moment the other day to clean out my email spam folder and was amazed again at some of the crap that is out there and circulating. Frankly I pity the mums and dads, grandmas and grandpas who are still getting a handle on internet communications and are forced to wade through the mountains of spam content that spews from lowlife individuals trying to gain a dishonest buck.<div>No I don't want $US1,000,000 dollars deposited into my bank account from the estate of some poor soul who's only crime was to die in an African country that I've never heard of before and whose name I can't pronounce. I don't want to increase the size of my ... (and frankly I'm offended at the suggestion that I need any further augmentation), and I'm not in any way your acquaintance so don't address me as "Dear Friend".</div><div>But as good as my spam filter is, and as thankful as I am for it performing the job of raking through the rubbish that skates across the internet, I'm actually most thankful that English is a difficult language to master. It is that fact that provides us with the single biggest identifier of spam emails and allows us to differentiate them from their legitimate counterparts. Take this latest email as an example:</div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px; "><br /></span></div><div><span class="Apple-style-span" style="font-family: arial, sans-serif; font-size: 13px; ">Dear Friend<span> </span><br />I am Mr Ailudiko Razak working with Islamic Development Bank(ISDB)Ouagadougou Burkina Faso. I want to inquire from you if you can handle this transaction for mutual benefits/life opportunity for you and me.The transaction is about seeking your consent to present you as the next of kin/ beneficiary To our late customer over his fund US$25,Million dollars.<span> </span><br />He died with his family during their vacation journey. I am waiting for your response for more details. The fund is going to be share at the ratio of 60/30.30% for you and 60% for i and my family which we are going to use for investment.and 10% for outstanding expenses.<span> </span><br />Mr Ailudiko Razak</span><br /><div><br /></div><div>What self-respecting bank would ever communicate using such a poor command of the English language? Even if my spam filter had allowed this one to slip through the cracks, I'd have every opportunity to detect its stench simply from the malformed sentence structures and incorrect use of words.</div></div><div>So while the English language is the bastard child of centuries of conquerors arriving on the shores of the UK, it is now the greatest asset I have to protect me against cyber criminals.</div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com3tag:blogger.com,1999:blog-1213970075009789555.post-83517956011791711582010-09-16T11:55:00.004+08:002010-09-16T13:30:47.354+08:00Altium Morfik acquisitionAt last I can finally share with you some commentary about what has been rattling around the corridors here at Altium HQ for some time. We've just formally <a href="http://www.asx.com.au/asxpdf/20100916/pdf/31sjnqg3tg2hkt.pdf">announced</a> our intention to acquire Morfik and it's very exciting.<div><br /></div><div>Picture this. You're an electronics designer and you've got a great idea for a new gadget. You've got all the skills necessary to design a PCB with some smarts in it and you can even program those smarts yourself. But then you come to adding some connectivity to the internet. You add an ethernet interface, update your smarts, and now you're ready to do the cloud stuff .... and you hit a brick wall. All that stuff about PHP and SQL and internet servers and SOAP and HTML and XML and Java and Ajax and ... It's a whole 'nother world!</div><div><br /></div><div>So what do you do? As an electronics designer, you know about bits and bytes and if you were ever pushed on the point, you could probably even design the hardware for a web server. But when it comes to writing applications that exist in the cloud, where do you start?</div><div><br /></div><div>Put simply, the Altium Morfik acquisition is all about giving you that starting point right out of the box. The philosophy is that pretty soon, every little device will need to be somehow connected to the cloud to maintain its relevance and appeal. And when it comes to designing those little neddies, you've got to start thinking about how and what you're going to connect it to. How will you pass data between your device and the cloud? Will it be via email posts, a simple Web server running inside the device, or will it be some other technique?</div><div><br /></div><div>The cool thing about what Altium is up to is that pretty soon you won't need to worry about the implementation specifics of all that sort of stuff. Using Morfik's technology (which lets you write applications on a PC and deploy them into the cloud), and Altium's unified design strategy, you'll be able to co-develop new devices AND the cloud-based eco-systems that they plug into. So adding cloud connectivity and applications will be just as accessible to you as an electronics designer as it is to all those geeky CS dudes ;)</div><div><br /></div><div>Hopefully it won't be long before I'll get to show you how this stuff works in practice with some real demos, but for the time being, I suggest you take a look at the <a href="http://wiki.morfik.com/wiki3/How_Do_I_Videos">videos</a> on Morfik's website. We'll be adding more and more of this stuff under the Altium banner over time but take it from me, this is a state changer.</div><div><br /></div><div>If you thought that Altium was a little out there as an EDA company, now we're off in the cloud!</div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-6337064787893162652010-08-26T06:27:00.005+08:002010-08-26T07:17:59.086+08:00Who cares about inefficient codeAt the risk of stirring up a hornets nest, I'm getting really tired of the naysayers who quickly play the "it's not as efficient as hand-crafted code" card when a new, high-level programming or design technique comes along. They just don't seem to get it that the question of 'efficiency' extends well beyond the run time of the application. In the real world of commercial pressures, making successful products is not just about the performance of the end product. It's also about your ability to develop, deploy and maintain that product within the window of opportunity given to you by the market.<div><div>This little rant of mine was provoked again after I read a recent FPGA Journal article '<a href="http://www.techfocusmedia.net/fpgajournal/feature_articles/20100803-ni/">Drag and Drop vs HDL?</a>' by Dick Selwood. It was a well-written and informative article about National Instrument's continued push into FPGA design with their drag and drop design environment. But all three reader comments (as of today) focus around the efficiency of the code produced by GUI based design approaches. Now come on guys. Surely you can try a bit harder. Of course hand crafted code is going to be more efficient than GUI-based stuff. But that only matters when it matters! To write off the whole GUI-based approach on account of the few situations when it isn't suitable is way to short-sighted. And it's not like NI is taking away the ability to use hand-crafted code. They are simply giving you the choice.</div><div>The real problem with the "it's not as efficient as hand crafted code" argument is that although it sounds rational, it places us in a very dangerous position of being dismissive of the whole technique without giving further thought to whether that technique will be disruptive. If you ever get the chance to read <a href="http://books.google.com.au/books?id=SIexi_qgq2gC">"The Innovator's Dilemma"</a> by Clayton M. Christensen then I highly recommend you do. It gives some really strong reasons why it can be suicidal to ignore new technologies on the basis of how well they fit current market demands. Technology doesn't stand still. It continues to push on at a break neck pace. If we dismiss a technology today because it appears to be inefficient compared with established techniques, we run the risk of being blind-sided when technological advances suddenly make the inefficiencies irrelevant. By that time, it is too late to reposition ourselves around the new way of doing things. As the book puts it, the real question is not about efficiency, it is about how disruptive the 'new thing' will be.</div><div>So here are my rules:</div><div>1) If something looks slow, technology will make it fast.</div><div>2) If a new design technique raises the abstraction level, gets you to market faster, or allows broader access to growth technologies (i.e. disruptive), it will supplant other techniques.</div><div>3) There will always be a need for hand-crafted solutions. But the proportion of products that must be hand-crafted will decrease.</div></div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-28146757625900838162010-08-23T20:08:00.005+08:002010-08-23T20:50:01.405+08:00The difference between Vias and PadsA recent post on one of Altium's forums related to the fundamental difference between pads and vias. So because I thought it was an interesting question, I figured it was worth posting a blog entry about it.<br /><br />Pads are the connection point between copper on the PCB and leads on the component. They are a common part of component footprints and they can be through hole or surface mount. When they are through hole, they are virtually always drilled completely through the board. When they are surface mount, they only exist on either the top or bottom layer. Pads can have virtually any arbitrary shape however round, rectangular, and rounded rectangular are most common.<br /><br />Vias, on the other hand, are the means by which an electrical connection is routed between two layers. As such, they are part of the track net and not usually tied to the component footprint. They are always drilled and always round. The depth of a via can vary depending on whether it needs to pass between the outside layers of the PCB, an outside and inside layer (blind), or two inside layers (buried).<br /><br />So the big question is, "Are these two primitives similar enough to be merged as one?"<br />The short answer is No. And the reasons are multiple:<br />1) Pads make their connection to component leads by being soldered. This means that the properties of the pad must have consideration for the soldering process being used. Solder mask pullback, pad surfacing, size and shape are all dictated by the soldering process and the physical properties of the component lead being connected.<br />2) Pads need to support multiple sizes and shapes due to both the properties of the leads of components connected to them, and any heatsinking effects needed as part of the component's cooling.<br />3) The pads of low pin count surface mount components need to be thermally balanced to avoid any ill effects caused by different cooling rates. For instance, a pad on one end of a two lead component (such as a resistor) that cools faster then the pad at the other end can cause the component to stand on its head (tombstone) as the solder contracts.<br />4) Unless you are dealing with embedded passives (i.e. components that are placed within the layers of the PCB), it makes little sense to have buried pads. Blind pads could be argued for some leaded components but that would make the board very dependant on very accurate lead lengths being maintained by the component vendor. This is probably an unnecessary risk as component leads that are too long will cause the components to stand off from the PCB. In some instances this may be desirable but I suspect it would be more hassle than it's worth.<br />5) Pads must have a designation to indicate how component pins and pads must be aligned.<br />6) The primary conduction path of a via is through the hole barrel. The copper donut area on top and bottom of the via is simply there to provide a solid connection between the hole barrel and the top / bottom connecting tracks. Without this, the connecting track could be torn off when the via barrel is drilled during manufacture.<br />7) Because vias don't require solder to fulfill their purpose, vias can be tented (covered with solder mask) to ensure that no copper is exposed to the outside world. This limits the risk of oxidisation of the via copper.<br />8) Vias offer a path between layers and so it is meaningless to use anything other than round, donut-shaped entry/exit points.<br />9) Vias need not have any designation since they are unreleated to components. However some form of unique ID would be helpful when devising design rules intended only for specific vias (of specific nets).<br /><br />So in summary, Vias and Pads might appear similar but their functions are quite separate. And in my view, they should remain as separate primitives. Comments?Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com6tag:blogger.com,1999:blog-1213970075009789555.post-32605865354403121132010-05-19T11:08:00.006+08:002010-05-19T13:05:06.801+08:00Schoolies week in India<div><div>This morning I had the opportunity to catch up with a valued colleague and friend <a href="http://emmalorusso.com/">Emma LoRusso</a>. One of the things I really value about Emma is her ability to see the way forward and devise the strategies to get there. Over some scrambled eggs and coffee, she helped calibrate and clarify a few thoughts I’ve been having and as a consequence, I want to share with you an idea and passion that I want to pursue.</div><div><br /></div><div>In 1999, I ventured on my first, short-term missionary trip to India. It changed my world. Having grown up in one of the most privileged countries in the world, I had never seen poverty like what I saw in India. So many people; so little material wealth.</div><div><br /></div><div>But even more confronting was the slow realization that maybe I was the one who was impoverished. In spite of all my material wealth and good fortune, maybe I was the one who had the greater need. </div><div><br /></div><div>The defining moment came for me when I shared a meal with an Indian family in a village whose name I could never pronounce. From a woodfire that had been cut into the earthen floor of what would otherwise be the verandah, the mother of the house served a bowl of rice with chicken curry that was so heavily spiced that it made my hands burn. And as I sat on the edge of the bed that doubled as their couch and begin eating with bare hands, it was as if my eyes had suddenly gained their vision for the first time. With the material facade pulled away I could see the world in a new light, and that the essence of living ran much deeper than my material possessions would have me believe.</div><div><br /></div><div>This epiphany was profound but no amount of words would allow me to convey it to you in all its richness; you must experience it for yourself. Somehow, I must take you there.</div><div><br /></div><div>And so I want to create a ‘Schoolies week in India’ program that gives you that opportunity. I want to take you out of your comfort zone and show you places and people that will change your world. And I want you to take that experience as a young adult and combine it with your passions so that you can know what to do with your future. This is <i>my</i> passion.</div></div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com1tag:blogger.com,1999:blog-1213970075009789555.post-11799227313344249922010-05-10T14:26:00.002+08:002010-05-10T15:00:12.760+08:00Why Government grants don't workHaving purchased a house around 8 months ago and now having experienced 6 interest rate rises in that time, I find it interesting to hear the ongoing debate about the rising cost of housing in Australia followed by demands for the government to "do something about it!" In typical political fashion, the Australian Government has been throwing money at new home buyers to help them live the Australian dream as well as stimulate the economy throughout this Global Financial Crisis. But I seriously doubt that this has been a useful exercise. In essence I believe it has actually hurt those people that it was intended to help.<br />For starters, housing affordability is driven by two forces; the first is the size of the deposit and the second is loan serviceability. Throwing money in the form of a one-off grant to first home buyers certainly helps them with their deposit but it does nothing to help with loan serviceability. And to make matters worse, because so many new home buyers have been clambering over the top of each other to get into the market and access their government grants, it has artificially inflated new homes by an amount roughly equal to the grant. In effect, the grant has passed straight through the hands of the borrowers and into the hands of the developer.<br />Solving the affordability problem is going to take a lot more than new home-buyer grants. The problem has to do with supply and demand. Everyone wants to live in a nice suburb and have access to good services. But that is an infrastructure issue as much as anything else. You can't create more land, all you can do is make better use of the land you have. And that's not something I hear the government doing anything about.<br />Why do we all feel we have to live close to the major capital cities? - So we can access good employment opportunities and education for our kids. Why do we want good employment opportunities? - So we can afford a nice house that's close to the city. And so the cycle goes.<br />So in my view, the only way to resolve the housing crisis is to provide incentives for industries to establish themselves in under developed areas of Australia. Rather than hand outs to new home buyers, why not invest in some real infrastructure and designate satellite cities that offer tax breaks to companies to establish there. Why not start building hospitals and schools <span style="font-style:italic;">before</span> people live there rather than waiting until they have to fight for it?<br />I met a lady the other day who was selling up from her Northern Beaches property in Sydney and moving to the country. With the proceeds of her suburban house sale she was buying a 7-acre allotment with a large house and 'plenty of room for her daughters to own and ride horses'. The family opportunities in the country were so much greater than what could be afforded in the city.<br />So perhaps a little more lateral thinking around the problem would see us making better use of this land that we have rather than having us all feel like we have to cram into shoe boxes just so we can be close to the big cities.Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-46037343240372262592010-04-29T14:54:00.005+08:002010-04-29T16:23:11.016+08:00Socially Connected DevicesThere's no shortage of people shouting about <a href="http://www.socialmachinery.com/2009/10/27/50-billion-devices-connected-by-2020/">50 billion devices being connected by 2020</a> but frankly I find all these futuristic discussions a bit shallow and without any real insight. People talk about everything being connected to everything and how your refrigerator will be able to order more milk when you run out (or something like that). But their arguments all seem to be built on an evolutionary model of connectivity expansion rather than a revolutionary one; there doesn't seem to be state change in how devices will communicate, just a whole lot more of them. So let me share with you where I think it is all going.<br /><br /><b>1st Generation Internet:</b> All about getting big ugly machines to be able to transfer data between one another where the nature of the data was only meaningful to the computers at each end of the communication pipe.<br /><br /><b>2nd Generation Internet:</b> People start getting involved and applications such as email allow people to start communicating with other people across the internet. The internet begins its amazing growth phase and websites designed for human interaction emerge.<br /><br /><b>3rd Generation Internet:</b> Social Networking. Broadcast and community-based forms of communication emerge. Instead of using point to point emails to talk to the world, people broadcast their status using sites such as YouTube, Facebook, Twitter and Blogs.<br /><br />OK, so hopefully you are still with me because here's where it gets interesting. We are currently in the 3rd Generation phase but the most interesting part is where its going from here. If we think that 50 billion devices are all going to start talking to one another, then what will they be saying? What will be the <i>style</i> of their communication?<br /><br /><b>4th Generation Internet: <i>Socially Connected Devices.</b></i><br />By combining concepts related to the previous generations, 4th generation internet devices will communicate with one another in much the same way as humans interact on social networks; a device will broadcast its status / opinion / desire for information, etc to the 'cloud' and let other devices on that cloud respond in a manner similar to human social networks. Devices would comment on the status or opinion expressed by the original device; I agree, I disagree, I have a similar idea but my information is based on different inputs, etc. and they would adjust their own operation (opinion / status) based on the information they receive. They could supply information according to the original broadcaster's request, or they could attempt to open up a point to point communications channel with the original broadcaster in order to resolve, clarify or expand on the original topic of discussion.The point here is that (unlike the 1st & 2nd generation internet) communication is rarely point to point. It is far more communal in nature and provides all members of the device's social community an opportunity to engage further. Devices are no longer dumb robots that happen to be connected to the internet, they are intelligent and capable of forming 'opinions' as they communicate with other <i>Socially Connected Devices</i>.<br /><br />To illustrate the concept, consider an example: On a hot day in summer, all the air-conditioners across the city are running flat out to keep homes and buildings cool. To help with their efficiency they monitor the open air humidity, temperature and sun load, and they broadcast this information to the cloud along with their location. As a cool change arrives and begins to travel across town, a sudden drop in temperature and sun load is measured by outlier buildings and they report this news to the cloud. Over time, more and more buildings report this change in temperature and a trend of information begins to emerge. Buildings that are yet to be hit by the cool change take note of the trend and check the local weather site to see where the prevailing winds are coming from. They quickly deduce that they are in the path of a cool change and so rather than continuing to listen to their own sensors that are telling them the sun load is still quite high, they listen to the outside opinions of other devices that are telling them that a cool change is on its way. With knowledge of the thermal mass of their building and an estimate of when the cool change will arrive at their specific location, they adjust the cooling output of their chillers at just the right time to ensure a more consistent temperature is maintained within the building and power is not wasted. And in the background of all of this, the power station throttles its output to manage the requirements of the network.<br /><br />Maybe it all sounds a bit futuristic but the technology to do it is all here today. So very soon I expect to see my smart house Tweeting its status to a whole cloud of <i>socially connected devices</i>.Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-45175511935217416992009-12-31T08:56:00.004+08:002009-12-31T09:47:03.945+08:00Are you still alive?Well it's been way too long since my last post and if you've read some of the user comments on previous postings, the last thing I want you to think is that I've somehow been shut down. Nothing could be further from the truth! But I have been <b>very </b>busy.<div>My wife and I bought a house back in September and it seems that every spare moment in the 6 weeks prior to that and since has been taken up with moving preparations, the actual move, and then renovations. So far we've managed to repaint all the bedrooms but the next job is to remove a wall in the main living area and then remodel the kitchen and lounge area. On top of that we need to remove all the carpets and sand the wooden floor boards back. I'm exhausted just thinking about it.<div>Our house is in <a href="http://maps.google.com.au/maps?f=q&source=s_q&hl=en&q=&vps=1&jsv=196c&sll=-25.335448,135.745076&sspn=75.886509,107.138672&ie=UTF8&geocode=Fb7K_f0dmKgECQ&split=0">Warriewood</a> which is about half way up the Northern Beaches region of Sydney. It's a great location and we are only about 1km from the beach (around a 10 minute walk). I really want to be well connected with my local community and so on top of all the moving and renovating, I also did the Surf Bronze Medallion qualification which lets me volunteer as a <a href="http://www.slsa.com.au/default.aspx?s=_becomeasurflifesaver">Surf Lifesaver</a> at my local beach - <a href="http://www.warriewoodslsc.com.au/">Warriewood SLSC</a>. Hopefully this will also come in handy with some other things I'm involved in such as <a href="http://www.surfforlife.org.au/">Surf For Life</a>.</div><div>On the professional front, the major landmarks were a trip to the US for a week to discuss some higher level opportunities (still hush hush), an editorial webcast discussing the <a href="https://event.on24.com/eventRegistration/EventLobbyServlet?target=registration.jsp&eventid=156178">impact of high level software on embedded design</a>, a webinar discussing <a href="http://www.altium.com/community/events/en/ecadmcadwebinar.cfm">how ECAD and MCAD design processes can merge</a>, sponsorship and attendance at <a href="http://fpt09.cse.unsw.edu.au/">FPT'09</a>, and creating a wacky <a href="http://www.youtube.com/watch?v=6auFcL3Qubo">NB3000 based Christmas Light Display</a>.</div><div>So as 2009 draws to a close, I can definitely say that it has been a very full year and yes, I am very much alive. There are some very exciting opportunities emerging for 2010 that I hope to share with you soon so stay tuned.</div><div>Happy New Year.</div><div>Marty</div></div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-8757212235629336102009-10-02T06:58:00.000+08:002009-10-02T06:59:14.676+08:00You get what you pay for<p class="MsoNormal"><span lang="EN-AU" style="mso-ansi-language:EN-AU">The other week I was passing one of my local car dealerships and I noticed a car brand that I hadn’t seen before.<span style="mso-spacerun:yes"> </span>It was a Chinese manufactured 4x4 and it was listed at about $20K less than a similar 4x4 that I’ve had my eye on for awhile. Of course my initial reaction was it couldn’t be all that good but in spite of that, I took one for a test drive.<o:p></o:p></span></p> <p class="MsoNormal">To my surprise, I can honestly say that it wasn’t an entirely horrible experience and I was <span style="mso-spacerun:yes"> </span>seriously considering my options. There were a few niggling things such as very heavy suspension and a driver’s side mirror that didn’t fold out far enough but overall it felt like a pretty solid vehicle. When I returned it and started talking turkey with the salesman, I asked him about the extra options. I wanted tinted windows, a tub-liner and canopy for the rear tray, and a towbar.<span style="mso-spacerun:yes"> </span>As expected, they were all additional options that pushed the price up by about $3000 but hey, you get what you pay for right?</p> <p class="MsoNormal"><span lang="EN-AU" style="mso-ansi-language:EN-AU">Ok, I agree. For most things you do in fact get what you pay for.<span style="mso-spacerun:yes"> </span>But does that also mean that if I want less, I can expect to pay less?<span style="mso-spacerun:yes"> </span>Altium Designer is a unified design tool that includes (amongst other things) PCB, FPGA, </span><st1:place><st1:stockticker><span lang="EN-AU" style="mso-ansi-language: EN-AU">CAM</span></st1:stockticker></st1:place><span lang="EN-AU" style="mso-ansi-language:EN-AU">, Simulation, and Embedded Software development capabilities.<span style="mso-spacerun:yes"> </span>So should I expect to pay less if I don’t want the FPGA bits? Or maybe I don’t want the embedded software stuff; can I pay less if I leave that out?</span></p> <p class="MsoNormal">How you respond to this question really depends on your philosophical position.<span style="mso-spacerun:yes"> </span>If you think FPGA or Embedded Software is an optional extra, then you’d rightly expect to not have to pay for it if you didn’t want it. But what if it isn’t? What if FPGA and Embedded Software development is a necessary part of sustainable product development? Surely it should always be included as part of the ‘base model’.</p> <p class="MsoNormal">Put another way, what if I wanted to buy a Volvo without airbags? Will they sell it cheaper? What if I only want two forward gears, can I remove the top three gears and get a discount? Of course not. The reality is that these <i style="mso-bidi-font-style: normal">features</i> are so much a part of the complete product that it doesn’t make much sense to try to remove them.</p> <p class="MsoNormal">In the same vain, Altium views FPGA and Embedded design capabilities as being so fundamental to the future of electronics product development that it makes no sense to treat them as optional extras or ‘delete items’ that you can take off the price.<span style="mso-spacerun:yes"> </span>We are all heading towards a future built on smarter products that continue to increase their reliance on functionality defined in the soft realm, and whether today’s customers choose to use these capabilities or not will not change the inevitability of that future.</p> <p class="MsoNormal">Maybe you do get what you pay for, but maybe you need more than you realize.</p>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-9404655280905064422009-07-27T12:06:00.004+08:002009-10-02T07:04:46.684+08:00Being free to succeedAs a subscriber to <a href="http://sethgodin.typepad.com/">Seth Godin's blog</a>, I was reading a recent post on <a href="http://sethgodin.typepad.com/seths_blog/2009/07/the-reason-riding-a-unicycle-is-difficult.html">The reason riding a unicycle is difficult</a>. As it just so happens, I taught myself to ride a unicycle a couple of years ago (some brief footage <a href="http://www.youtube.com/watch?v=mwtUo7CgRdQ">here</a>) and what Seth mentions about falling is quite true. To ride a unicycle, you actually need to sit up straight and lean forward as if you're about to fall. But to save yourself, you pedal to catch up and before you know it, you're riding. So the key to riding a unicycle is finding that knife edge between falling flat on your face and moving forwards.<div>A few years ago, some friend's kids came away with us on holidays and I promised them I would teach them to ride. Their names were T. and D. and they were about 6 & 5 respectively. T., being the boy, was right into it and took off like a flash. After barely an hour of running behind him, he was off like a pro. But D. took a bit more work. After the first fall or two, she was ready to give up. It seemed that everytime she got going, she fell off. To her, riding was pain and not something worth pursuing. I could see that I needed to change my approach.</div><div>So instead of teaching her to ride, I started teaching her to stop. We did a few practice stops where I held her on the bike and without it moving forwards, I got her to take her foot off the pedals and place it on the ground as the bike fell to the side. Once she mastered that simple skill, integrating it with moving forward was just a matter of practice. After a day, she was up and doing laps alongside her brother. By taking the fear out of the fall, she was suddenly free to succeed.</div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-54049582739950899342009-07-15T08:02:00.004+08:002009-07-15T08:53:34.667+08:00Avoiding conflict with customer serviceWith the kids on school holidays and in another city with my parents, it was high time my wife and I got away for a weekend together. We found a hotel/resort online, phoned ahead to make a booking, and leisurely drove down to the NSW south coast.<br />At the time of making the booking, I had requested a dinner reservation for 7:30pm. When we arrived however, the hotel reception informed us that a reservation had been made for 7pm. Later, when we fronted at the restaurant at 7pm, we were told that the reservation had, in fact, been made for 8pm and that a table would not be available until that time. Slightly inconvenienced, we went back to our rooms with the prospects of our stomachs churning over for another hour. But at 7:30, I received a call from the restaurant to inform me that a table had now become available and we could begin our dining immediately if we so desired.<br />So in the end, we got the dinner reservation at the time we originally requested but not without some mucking around. I noted all of this on the hotel feedback form when we checked out. The hotel receptionist was very pleasant and smiled warmly as she finalized the invoice. "Did you consume anything from the minibar?, No? Well that's all paid up then. Did you enjoy your stay?"<br />I hesitated for a moment. Do I tell her that we had been stuffed around by the dinner reservation? Or do I simply return her smile and not mention it?<br />I chose the latter after convincing myself that I had written all my grievances in the hotel feedback form and that there was no need to make a scene by going over old ground. But as I walked back to my car and drove off, I pondered this interaction.<br />I've done enough customer service stuff to know that for every 1 person who complains about something, there are at least 10x that many people who have probably felt similarly but have chosen not to say anything for fear of 'making a scene'. So when someone does indicate that their expectations have not been met, it is well worth the effort to resolve things both for them and to ensure the same thing doesn't happen again. But for me, telling the hotel receptionist that I had felt let down by the restaurant booking would have created a position of potential conflict between the two of us and that really wasn't something that I wanted to come between my weekend away with my wife. It was just easier to avoid the conflict altogether and move on.<br />But in doing this, I had let an opportunity for improvement pass by the hotel.<br />I started thinking if there was a better question that the receptionist could have asked that would have solicited my feedback without creating a sense of conflict between us. I concluded that a better question might be, "Is there any feedback that you would like me to pass on to management for you?" All of a sudden, the receptionist is no longer my adversary but is now my advocate. My grievance was not between me and her. It was with a faceless hotel reception system that had mucked my dinner plans around. And yes, that IS something that I would like passed onto 'management'.<br />By asking this slightly better directed question, the receptionist would have created the opportunity for much better feedback without creating a position of confrontation between us. By introducing 'management' as a third party into the discussion, she would invite me into her confidence and create an atmosphere of much better customer service. So while I honestly did enjoy my stay, the hotel is much more likely to receive the valuable feedback it needs through a better framed question.Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-21450903010908968652009-06-29T12:18:00.004+08:002009-06-29T13:54:27.983+08:00Avoiding Premature EvaluationI was recently part of some discussions with company 'NoName' who had been evaluating Altium Designer. They knew a thing or two about FPGAs and so that's where they had headed first. When they found the schematic editor and the library of FPGA-specific components, they figured they understood what Altium Designer was all about and formed the (premature) conclusion that it was just another schematic-based FPGA design system.<br />When I questioned 'NoName' about their conclusion, they revealed, "We evaluated the design tool in line with how we felt a design tool should work." It's hard to argue with that logic and the reality is that their conclusion wasn't actually wrong - Altium Designer does allow you to do FPGA design using a schematic-based workflow. But it offers so much more than that and it was my job to help them see that.<br />Given that we all live in such an information rich environment, most of us have developed sophisticated filtering systems that allow us to order the information we we receive each day into nicely contained buckets. This works really well with well-behaved information that conforms with our pre-existing classification system. But what about the other things? How do we handle that?<br />That depends on whether we think the information is <em>likely</em> to be well-behaved or not. If we think it is well-behaved, then we will probably try to stuff the new information into one of our existing buckets. If we think it isn't well-behaved then we may try to put it into a couple of buckets. And in very rare circumstances, we may even consider making a paradigm shift and changing our entire bucketing strategy. <br />The problem with paradigm shifts is that we don't always know when we need to make one. Because we spend most of our time packing new information into existing buckets, our brains get very used to that sort of routine. So when something comes along that would warrant a paradigm shift, we may overlook it in our haste to stuff it into a pre-existing bucket.<br />That is how I would describe 'NoName's' initial reaction to Altium Designer. They thought they knew what they were looking at, they confirmed their ideas through some initial investigations, and once the classification process had concluded, they saw little reason to reconsider their conclusion. But to their credit, 'NoName' proved extremely open-minded and allowed me to discuss Altium Designer further with them. As a result, I was able to show them the features beyond the schematic entry capabilities and the overall exchange of information was quite valuable.<br />So if you're suffering from premature evaluation too, then maybe its time we talked about it.Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-19109962680825163312009-05-20T20:29:00.006+08:002009-05-20T20:50:22.642+08:00The Best Switch Debounce Routine EverSwitch debouncing is the process of filtering out the mechanical chatter that comes from switches (and relays) when their contacts touch or release. The duration of the chatter depends on the physical properties of the contacts but can last for as long as several tens of milliseconds. A comprehensive backgrounder to switch debouncing can be found <a href="http://www.ganssle.com/debouncing.pdf">here</a> so I won’t repeat that content here. But I want to share with you an effective software debounce routine that is elegant in its simplicity, efficient and perfectly scalable.<br /><br />Consider the following ‘bouncy’ signal.<br /><br /><img id="BLOGGER_PHOTO_ID_5337882799585588018" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 99px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmWRk_D53rpdFK5__FsLZa9UP5bE9tYzhOek2IvJJWt6lIRgcPnaMTitmMwIqZ2Qz5CA0XPayjNKnxQaJYMtU3Av7hKwJs3hAEMTGcJzOxdpkjYQ36mz4dXATa464uylqVshyphenhyphenrloisqZY8/s400/BouncySignal.JPG" border="0" />Up until t=3, the input signal is in a low state. At t=3, some EMI induces some spurious noise on the wire that we want to reject. At t=5, the switch is in a bouncy state as a result of being activated. And at t=6 and beyond, the switch is in a stable high state.<br /><br />The goal of the debounce routine is to reject spurious signals such as those found at t=3 while still reporting a valid transition within a timely fashion. This can be done by taking periodic samples of the signal and reporting an update once several samples agree with one another. The exact number of samples and periodicity will depend on the environment that your application will be used in and the immediacy that you need to report an update.<br /><br />So let:<br />A = Current Switch Sample (T=0)<br />B = Previous Switch Sample (T=-1)<br />C = Sample taken prior to B (T=-2)<br />Z = Last reported debounce value<br />Z’ = New debounce value<br /><br />If (A = B = C) then<br />Z’ = A<br />Else<br />Z’ = Z<br />EndIf<br /><br />We can create a <a href="http://en.wikipedia.org/wiki/Karnaugh_map">karnaugh map</a> for Z’ using the inputs A, B, C and Z.<br /><p><img id="BLOGGER_PHOTO_ID_5337883443489034642" style="DISPLAY: block; MARGIN: 0px auto 10px; WIDTH: 400px; CURSOR: hand; HEIGHT: 117px; TEXT-ALIGN: center" alt="" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgmYlk5NXqaeKwlb4qV5rYPlx8eYosFivwrbxrbqgJqMR7djoNLKqfR3qmLFUjOR7TCaEdVhGpUmoCj7KaI1n-zZTs-a2kIaPTOwuZtqgrywUqjEXglQUs5GS41tDsjI1DH473ogMKMjcCI/s400/KMap.JPG" border="0" /></p><p>There are a number of benefits to this routine over other routines I've seen:<br /></p><ol><li>It works for debouncing an entire input port as well as individual bits.</li><li>It doesn’t consume any timer resources other than those required to periodically call the routine.</li><li>It can be readily implemented in programmable hardware, and</li><li>It is perfectly scalable. So you can expand the number of samples without modifying the basic algorithm. For instance, the equation for debouncing across 4 samples is:<br />Z’ = Z(A+B+C+D)+A.B.C.D<br />And the equation for sampling across 5 samples would be:<br />Z’ = Z(A+B+C+D+E)+A.B.C.D.E </li></ol><p align="left">A sample C routine is listed below (please excuse the formatting):<br /><span style="font-family:courier new;font-size:85%;">int debounce(int SampleA)<br />{<br /> static int SampleB = 0;<br /> static int SampleC = 0;<br /> static int LastDebounceResult = 0;<br /><br /> LastDebounceResult = LastDebounceResult & (SampleA | SampleB | SampleC)</span><span style="font-family:courier new;font-size:85%;"> | (SampleA & SampleB & SampleC);<br /> SampleC = SampleB;<br /> SampleB = SampleA;<br /> return LastDebounceResult;<br />}</span></p>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com13tag:blogger.com,1999:blog-1213970075009789555.post-14299815007238596882009-04-30T10:02:00.006+08:002009-04-30T11:57:43.524+08:00What is your sense of entitlement?In my <a href="http://drmarty.blogspot.com/2009/04/altiums-new-pricing-model.html">last post</a> I mentioned that Altium have stirred the pot with their new pricing model. Well now they've gone even further with a web-based advirtising campaign and <a href="http://www.flickr.com/photos/altium/3484454699/">billboard promotion</a>. The text is a little hard to see in the photo so I've included it here:<div><br /></div><div>1,000,000 people overseas can do your job</div><div>What makes YOU so special?</div><div>Altium. Next generation electronics design solutions.</div><div><br /></div><div>Not surprisingly, its caused a rise out of more than a few people with one person stating that Altium should sack their ad agency and the foolish executives who approved this indignity. It is certainly a stark departure from the "You're so special" sort of advirtising that we're used to seeing.<br /></div><div>But it has got me thinking about the sense of entitlement that we have around our work, our skills and our job. What is at the core of our indignation over someone overseas taking our job?<br /></div><div><a href="http://www.gymeabaptist.org.au/KarlFaaseProfile.aspx">Karl Faase</a>, a regular "life moments" radio presenter, recently had this to say on one of the local community radio stations:</div><div><br /></div><div><span class="text11">The present generation has grown up believing that every child needs good self esteem. Every child needs to believe in themselves and their ability. But is there a potential down side to this attitude? Over the past 20 years American children have grown up being told they are special and can achieve anything and now there seems to be a growing gap between American kids’ self esteem and their abilities.<br /></span><span class="text11">In a study of maths skills tests among students in eight nations, Americans ranked lowest in overall competence and Koreans highest, but when researchers asked the students how good they thought they were, the results were exactly opposite; Americans highest, Koreans lowest.</span><br /></div><div><span class="text11">We need to be realistic about our abilities. </span><span class="text11">A</span><span class="text11">s writer Steve Salerno says “In the grand scheme of things, knowing one's limitations may be even more important than knowing one's talents.”</span><br /></div><div><br /></div><div>When it comes to designing electronics products, the days are gone when our value was implicit in the degree or qualifications we had earned. We have jobs for the simple reason that we add value to the companies that employ us. It is an issue of economics and not entitlement. The only defence is continuous innovation.<br /></div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com1tag:blogger.com,1999:blog-1213970075009789555.post-5182843164327617492009-04-27T11:46:00.004+08:002009-04-27T12:05:52.104+08:00Altium's new pricing modelI can hardly believe it's been over a month since my last post.<div>Things are progressing nicely on our target project but it has taken quite a few twists and turns over the past 6 weeks as has the focus of the objective. I can't say too much at this point 'cause it aint public yet but all will be revealed soon (very exciting!).</div><div>Last week we released <a href="http://altium.com/products/altium-designer/en/altium-designer_home.cfm#options">new pricing for Altium Designer</a>. It's been really interesting to see the user response to it on the <a href="http://forums.altium.com/forums/190249/ShowPost.aspx">forum</a>. A number of people have reacted to the fact that our huge reduction in price has severly depreciated their purchase. Others have just been happy that Altium tools will be more accessible to the broadest possible range of designers. Yet others have taken the synical view that it is simply a grab for cash in tough economic times. From the inside though, I can honestly say that I am excited about the pricing decision as I know it will help a lot of struggling engineers and companies out there and it will ensure that price is much less of a barrier.</div><div>So let me know what you think. Is it still too much? Or is it too little - i.e. will the "you get what you pay for" adage work against it?</div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com12tag:blogger.com,1999:blog-1213970075009789555.post-58787531276802751612009-03-13T06:39:00.004+08:002009-03-13T07:10:19.306+08:00Fail fast, fail cheapOften when we try to build something, the very last thing we consider is failure. But it is actually through our failures that we learn the most and find the path towards true innovation. So rather than avoiding failure, we should focus on sandboxing our thoughts in a way that captures failure early and cheaply.<div>Let me offer a recent example. You've heard me talk about the <a href="http://drmarty.blogspot.com/2009/02/what-would-you-like-to-see-me-design.html">new design</a> that I'm working on for an upcoming training program we are running at <a href="http://www.altium.com/">Altium</a>. Well I thought we were going to go ahead with the <a href="http://drmarty.blogspot.com/2009/02/project-begins.html">Natural Disaster Management System</a> but that got canned because we didn't want users to pay several hundred $$$'s in weather measuring equipment in order to replicate the project.</div><div>So the new project is a moving light system. Basically it involves mounting a <a href="http://www.luxeonstar.com/endor-rebel-rgb-triemitter-p-184.php">high powered LED</a> onto a pan-tilt head (something like <a href="http://www.lynxmotion.com/images/Products/Full/bpt01.jpg">this</a>) and creating a moving light show that can be controlled from a myriad of sources.</div><div>According to info I found on the <a href="http://www.seattlerobotics.org/guide/servos.html">web</a>, driving R/C servo motors is pretty easy. So I thought getting one to work would be a piece of cake. In actual fact it was pretty easy but after connecting up the first servo, its range was only about 90 degrees. I needed at least 180. No problem, tweak the driving circuit a bit and before you know it I had it driving across the full 180. As it happens, the generic servo drive specs didn't seem to match up with the servos I bought and I had to spread the signal out a bit to get the full range.<br />So in a word, my first attempt failed, but that's what lead me to the second attempt and a greater understanding of what I am working with. I now know that I need to leave provision in the application code so that I can calibrate for any servo to ensure I get the full range out.</div><div>So fail fast, fail cheap, and move on to the real innovation.</div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0tag:blogger.com,1999:blog-1213970075009789555.post-19077790248876824472009-03-05T05:34:00.001+08:002009-03-13T07:48:06.076+08:00Forget what you know. It is hindering your progress.Some time ago, I found myself at some sort of big self-help thing that gave the facade of helping you unlock your own potential and find a new state of being, but at $600 for the "introductory" program, it smelt a bit like someone's money-making system. In the end they didn't get my money but I did manage to pick up a bit of free advice. They broke knowledge into three types:<div><ul><li>The things I know that I know</li><li>The things I know that I don't know, and</li><li>The things that I don't know that I don't know.</li></ul>The things I know that I know are things like my birthday, my parent's names, the approximate speed of sound in air, etc. The things I know I don't know are things like the exact population of my city, the volume of sydney harbour, the mind of a woman.</div><div>Now when it comes to the things that I don't know that I don't know, well I can't give an example for the simple reason that if I could, it would be classified in the one of the previous two categories. The point of that expensive self-help program was simply that the key to unlocking your potential lies in your ability to be open to the things that you don't know that you don't know. It kind of messes with the mind a little but if you think about it, it actually makes good sense.</div><div><br /></div><div>But I have been pondering some of these thoughts in the last day or so and I think I can add a new category to the list:</div><div><ul><li>The things I think I know that I really don't know</li></ul>When it comes to the rapid movement of technology, it is this very thing that hampers our ability to reach for the stars. Technology is continuously changing the rules. We think we understand the game and so we start playing it one way. After a little while, we check the scoreboard only to find that we have actually been playing on a field that is far removed from where the real game is at. Why? Because we thought we knew something and so we didn't think that we needed to check it again.</div><div><br /></div><div>We are living in the so-called information age. Information is available to us like never before in history and is being continuously expanded on at a break neck pace. As a consequence, our brains have developed keen filtering processes that help us partition up information and navigate our way through. Some things we accept on face value. Other things we examine more closely. But having reached a conclusion about something, we rarely revisit it unless we perceive that some other piece of new information warrants a rethink.</div><div>But what if we never receive that new piece of information? What if we continue on our way thinking that we know something when in fact we don't? We are actually in a worse state than absolute ignorance. We are trapped in an erroneous paradigm with no way to get out and no sense that we are in the wrong place.</div><div>To add to the deception, we often build on our conclusions. So conclusions that we have arrived at in the past will often form the basis of further conclusions that we make today. But what if our original conclusion is wrong and we don't know it? All of a sudden the house of cards starts tumbling down.</div><div><br /></div><div>In the film "The Matrix", Neo is encouraged to free his mind; to not be constrained by what he thinks is real. In the Matrix, there are rules that are meant to be bent, and some which are meant to be broken. By thinking that we know what we know, we forget to question where our degrees of freedom lie. Because of what we 'know', we hinder our progress.</div>Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com3tag:blogger.com,1999:blog-1213970075009789555.post-24488324537904283752009-02-26T19:11:00.000+08:002009-02-26T19:57:55.248+08:00The project beginsWell it's been way too long since the last post but I've been flat out. I've been testing a range of new components that we want to use in our project board. The idea is that we prototype each of the various sub-circuits to make sure we don't end up with any surprises when the first proto pcb comes back. So far its proved a very fruitful exercise.<br />One of the devices I had to check out was a <a href="http://www.princeton.com.tw/downloadprocess/downloadfile.asp?mydownload=PT2300.pdf">2W audio amp</a>. Now apart from the poor english in the datasheet (Example: When driving a speaker load suggestion set to the BTL mode for get the more power output.), the application circuit was drawn with the shutdown connection wired ON - i.e. to VCC. So without thinking, that's how I wired up the test circuit. When I got nothing coming out of the amp, I probed a little further, went back and read the data sheet, and realized that ON meant the shutdown was on, not the amplifier was on. Shutdown ON = amplifier OFF!<br />A quick rewiring of that pin and everything came to life - and quite impressively too. Given the mistake I made, I checked over the circuit that our hardware guy had created and sure enough, he'd been tripped up by it too. So it was well worth doing the quick prototype.<br />Next job was to test out the quality of some low priced speakers. They were tiny surface mount things and they sounded crap! I'm glad we did that check because it would have been a real let down if we'd gone ahead with them. It forced us to probe a little further and our sourcing guys found some great little beasties for about 70c each. They are 30mm across and use rare earth magnets and boy they can pack a punch. Unfortunately I don't have the specs on them just at the moment but I'll post a link later on.<br />I checked out a few other components such as an <a href="http://www.nxp.com/acrobat_download/datasheets/PCF2123_1.pdf">SPI-based Real Time Clock</a> and <a href="http://datasheets.maxim-ic.com/en/ds/DS2431.pdf">One-Wire ID chip</a>. Fortunately there were no surprises there but I've got to say, using Altium Designer to do the testing was a real breeze. They already have software drivers for SPI and One-Wire devices so it was pretty easy to get some basic test applications up and running.<br />So it looks like we are just about set to begin developing our first reference design. We had a brainstorm yesterday and came up with over 50 project ideas. But as we narrowed it down, we didn't want to spend all the time on developing the application. We wanted a project that would let us demonstrate the way to approach building a system without getting bogged down in the detail of developing a complex application. So it looks like the project will be a Natural Disaster Reporting System. The basic idea is that these units can be installed in people's houses and will log weather data back to a central site. In return, that site can send emergency response information back to the units based on immenent danger from fires, hurricane, tsunami etc. It'll give us a chance to show how to interface to a number of IO devices as well as build a nice user interface for the LCD and perform some Ethernet comms. I'm looking forward to building it.<br />Oh, and as a very topical side note, we drove down to Melbourne last weekend and had to drive through some of the areas affected by the bushfires. We weren't trying to be nosey but you can't help but notice the huge devastation. There are warnings that the weather tomorrow might be pretty bad as well and my mother in-law is going to evacuate just to make sure. No one wants to take any chances after what happened three weeks ago. So maybe our little project might get some people thinking about ways to use technology to better manage people during Natural Disasters.Dr Martyhttp://www.blogger.com/profile/04621783114660710784noreply@blogger.com0