<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="bbPress/1.0.2" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>LeafLabs Garden &#187; Topic: Non-blocking serial transmit</title>
		<link>http://forums.leaflabs.com/topic.php?id=1142</link>
		<description>A place to share, learn, and grow...</description>
		<language>en-US</language>
		<pubDate>Fri, 22 Jan 2016 00:14:13 +0000</pubDate>
		<generator>http://bbpress.org/?v=1.0.2</generator>
		<textInput>
			<title><![CDATA[Search]]></title>
			<description><![CDATA[Search all topics from these forums.]]></description>
			<name>q</name>
			<link>http://forums.leaflabs.com/search.php</link>
		</textInput>
		<atom:link href="http://forums.leaflabs.com/rss.php?topic=1142" rel="self" type="application/rss+xml" />

		<item>
			<title>tdc218 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7120</link>
			<pubDate>Tue, 08 Nov 2011 21:28:47 +0000</pubDate>
			<dc:creator>tdc218</dc:creator>
			<guid isPermaLink="false">7120@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;I can read the control and status regs just fine, and I can change their settings - it all works until I try to enable the TXE interrupt.  I can pump characters into the DR and have them show up on a serial LCD, and it doesn't matter whether it's usart 1, 2, or 3, they all behave the same way.  It's all very confusing, this ought to be really straight forward.&#60;/p&#62;
&#60;p&#62;Anyway, since I'm kinda stuck and since my original method works, I'm gonna set this aside for a while and get back to work on my project.&#60;/p&#62;
&#60;p&#62;gblumer - thanks very much for all of your help.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7108</link>
			<pubDate>Mon, 07 Nov 2011 08:53:39 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7108@http://forums.leaflabs.com/</guid>
			<description>&#60;blockquote&#62;&#60;p&#62;... It behaves exactly the same regardless of whether the isr is in or commented out. Is that really an issue?&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;I believe a Maple sketch is compiled with a whole set of default interrupt handlers, most of which 'throb' the LED if they are called. So yes, I think it is an issue.&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;When you're just setting the enable bit, no interrupt should occur.&#60;/p&#62;
&#60;/blockquote&#62;
&#60;p&#62;So, assuming you have removed (commented out) the &#60;code&#62;USART3-&#38;gt;regs-&#38;gt;CR1 &#124;= USART_CR1_TXEIE;&#60;/code&#62;  and everything works okay (but does nothing), then we can conclude that that line of code breaks something.&#60;/p&#62;
&#60;p&#62;You can try to eliminate some potential errors, e.g. a bad address, by only reading the bit and not setting it:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;unsigned int txeie_bit = (USART3-&#38;gt;regs-&#38;gt;CR1 &#38;amp; USART_CR1_TXEIE)? 1 : 0;
SerialUSB.print(&#38;quot;TXEIE is &#38;quot;);
SerialUSB.println(txeie_bit);&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;If that works okay, then I think we can assume for now, there is something happening when the bit is set, and the likely cause is an interrupt. I don't know what happens if the USART triggers an interrupt, and the cause isn't dealt with. I'd expect it to continuously trigger. That might be enough to make a Maple behave badly.&#60;/p&#62;
&#60;p&#62;RM0008 27.6.1 &#34;Status register (USART_SR)&#34; says:&#60;br /&#62;
&#34;Bit 7 TXE: Transmit data register empty&#60;br /&#62;
This bit is set by hardware when the content of the TDR register has been transferred into the shift register. An interrupt is generated if the TXEIE bit =1 in the USART_CR1 register. It is cleared by a write to the USART_DR register.&#34;&#60;br /&#62;
So I would expect the interrupt service routine to either put a character into the USART_DR register (which may trigger a different interrupt), or clear the TXEIE bit.&#60;/p&#62;
&#60;p&#62;Is USART3 connected to anything? Can you pump characters down the wire?&#60;/p&#62;
&#60;p&#62;e.g. something dumb like:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;volatile unsigned char c = 0;

void __irq_usart3(void) {
      USART3-&#38;gt;regs-&#38;gt;DR = &#38;#39;A&#38;#39;+c;
      c = (c+1) &#38;amp; 0x1F;
      toggleLED();
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;would give you a bit more information.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>tdc218 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7093</link>
			<pubDate>Sat, 05 Nov 2011 21:00:08 +0000</pubDate>
			<dc:creator>tdc218</dc:creator>
			<guid isPermaLink="false">7093@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;That pretty much IS the whole program, but it follows.  It behaves exactly the same regardless of whether the isr is in or commented out.  Is that really an issue?  When you're just setting the enable bit, no interrupt should occur.  Also, isn't there already an isr?  usart.c says there is - sure, it's for servicing the receive interrupt, but it is there; it may not do anything intelligent if called by a tx interrupt, but that shouldn't crash the Maple.&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;#include &#38;quot;usart.h&#38;quot;

void __irq_usart3(void) {
      toggleLED();
}

void setup(void)
{
  pinMode(BOARD_LED_PIN, OUTPUT);

// wait for the serial monitor to be connected
  while(!(SerialUSB.isConnected() &#38;amp;&#38;amp; (SerialUSB.getDTR() &#124;&#124; SerialUSB.getRTS())))
  {
    toggleLED();
    delay(123);
  }
  digitalWrite(BOARD_LED_PIN, LOW);

 // set up the serial port
  Serial3.begin(9600);

// wait to make sure things are stable ...
  delay(2);

// and ...
  SerialUSB.println(&#38;quot;Enabling TXEIE...&#38;quot;);        // this prints
  USART3-&#38;gt;regs-&#38;gt;CR1 &#124;= USART_CR1_TXEIE;          // set txe interrupt
  SerialUSB.println(&#38;quot;TXEIE should be enabled&#38;quot;);  // this never prints
}

void loop(void)
{
}&#60;/code&#62;&#60;/pre&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7087</link>
			<pubDate>Fri, 04 Nov 2011 21:31:13 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7087@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;tdc218 - It is a bit hard to diagnose the problem without seeing the whole program.&#60;/p&#62;
&#60;p&#62;Would you either post a minimal program, or paste your program into pastebin and post a link here?&#60;/p&#62;
&#60;p&#62;One reason the led fades is when an interrupt service routine is missing.&#60;/p&#62;
&#60;p&#62;(full disclosure: I am not a member of LeafLabs staff.)
&#60;/p&#62;</description>
		</item>
		<item>
			<title>tdc218 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7086</link>
			<pubDate>Fri, 04 Nov 2011 15:39:46 +0000</pubDate>
			<dc:creator>tdc218</dc:creator>
			<guid isPermaLink="false">7086@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;So I've been playing with making this interrupt driven.  However, trying to set the TXEIE bit in CR1 seems to cause the Maple to crash.  My code:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;Serial3.begin(9600);

  SerialUSB.println(&#38;quot;Enabling TXEIE...&#38;quot;);
  USART3-&#38;gt;regs-&#38;gt;CR1 &#124;= USART_CR1_TXEIE;    // set txe interrupt
  SerialUSB.println(&#38;quot;Registers after RXEIE&#38;quot;);&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;The first line prints, the second line never does. If I try to upload the sketch again, it doesn't find the Maple and the on-board led fades in and out like something ASSERTed. I've studied RM008 and the usart.c code in libmaple and this looks exactly like what they do in the latter.  Is there some trick I'm missing?
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7062</link>
			<pubDate>Tue, 01 Nov 2011 09:50:16 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7062@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;tdc218 -&#60;br /&#62;
&#60;blockquote&#62;Instead of DMA, can you have your own interrupt service routine on TXE interrupt?...&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;Yes, absolutely.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>tdc218 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7059</link>
			<pubDate>Mon, 31 Oct 2011 19:45:35 +0000</pubDate>
			<dc:creator>tdc218</dc:creator>
			<guid isPermaLink="false">7059@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;In my application, I can easily tolerate the few microseconds that update burns off every time it's called far more than I can tolerate stopping the whole program for a few milliseconds every time I want to update the display.&#60;/p&#62;
&#60;p&#62;I took a brief look at DMA in the reference manual.  My head asplode.  ;)  If my admittedly quick reading of it is correct, one challenge seems to be that you set up the DMA and then don't bother it 'till it's done, so if more characters get added to the buffer while it's busy sending the last batch, you need some way to remember that and update it when it's done.  This seems like it could get rather unwieldy very quickly.&#60;/p&#62;
&#60;p&#62;Instead of DMA, can you have your own interrupt service routine on TXE interrupt?  That would make it really easy, something like:&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;void usart_tx_isr(void)
{
  if (!(rb_is_empty(&#38;amp;rb)))		// if there is a character to send
       xregs-&#38;gt;DR = rb_remove(&#38;amp;rb);      // then pull it from the buffer and send it
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;Yeah, it'll burn a few CPU cycles every character but unless you're in a real time critical situation so what?&#60;/p&#62;
&#60;p&#62;The putc routine would need minor alteration to kick start the usart if it were idle.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7058</link>
			<pubDate>Mon, 31 Oct 2011 18:27:11 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7058@http://forums.leaflabs.com/</guid>
			<description>&#60;blockquote&#62;&#60;p&#62;When I think of non-blocking, I think of something that's asynchronous with the main program.&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;Yes.&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;The simplest solution is to setup a timer that handles shoving data from the buffer to the hardware. ... &#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;A solution I think of is using a 'data arrived', or 'data sent' interrupt if there is a peripheral involved. This is exactly the time when data is ready or the peripheral is ready for more data. So it makes more sense (to me) than a timer.&#60;/p&#62;
&#60;p&#62;Connecting DMA to a &#34;ready&#34; signal is a straightforward improvement over the interrupt service routine.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>robodude666 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7056</link>
			<pubDate>Mon, 31 Oct 2011 11:48:14 +0000</pubDate>
			<dc:creator>robodude666</dc:creator>
			<guid isPermaLink="false">7056@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;When I think of non-blocking, I think of something that's asynchronous with the main program.&#60;/p&#62;
&#60;p&#62;The simplest solution is to setup a timer that handles shoving data from the buffer to the hardware. Since the STM32 is blessed with a powerful DMA controller, it's ultimately the better alternative. &#60;/p&#62;
&#60;p&#62;By giving the DMA controller (hardware) the responsibility of dumping data from the buffer to the serial peripheral you're insuring the non-blocking serial class to also be wait-free, which I think is important to achieve.&#60;/p&#62;
&#60;p&#62;Certainly, waiting a couple dozen cycles for &#60;code&#62;update&#60;/code&#62; to finish isn't much, but when you're dealing with time-sensitive situations it may be too much to wait.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>gbulmer on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7054</link>
			<pubDate>Sun, 30 Oct 2011 19:31:45 +0000</pubDate>
			<dc:creator>gbulmer</dc:creator>
			<guid isPermaLink="false">7054@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;robodude666&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;A true non-blocking serial class would use RAM to USART DMA transfers ...
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;I believe the meaning of 'non-blocking' is &#60;strong&#62;not&#60;/strong&#62; about whether DMA is used or not.&#60;br /&#62;
DMA can certainly be used to implement non-blocking I/O, but it isn't essential. The essential feature is only not to block !-)&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;Also, if the class is specifically designed to be a non-blocking serial class, under no circumstance should the class block.
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;Agreed.&#60;/p&#62;
&#60;blockquote&#62;&#60;p&#62;To support this, I think that puts and putc should return a BOOL, true or false, as to whether or not the buffer was full before attempting to insert the data. If the buffer cannot support the entire string of data, none of it should be inserted. A false is returned, and the user decides what they want to do.  ...
&#60;/p&#62;&#60;/blockquote&#62;
&#60;p&#62;This is one perfectly reasonable approach. &#60;/p&#62;
&#60;p&#62;A common alternative technique is to 'peek' and see that there is enough space available in the output buffer (tdc218 &#60;code&#62;space&#60;/code&#62; function) before trying to 'put' the characters. The disadvantage of only returning the &#60;code&#62;bool&#60;/code&#62; 'failed' is the program  doesn't know how much it's failed by, which I think is too little information.&#60;/p&#62;
&#60;p&#62;So using tdc218's approach, it is trivially easy to write a version of, e.g. nputs which returns a bool when there isn't enough space:&#60;br /&#62;
&#60;pre&#62;&#60;code&#62;void nbSerialTx::bool_fail_nbputs(char *s)
{
  char c;

  if (strlen(s) &#38;gt; space()) return false;

  while ((c = *s++))
    nbputc(c);
}&#60;/code&#62;&#60;/pre&#62;
&#60;p&#62;But it isn't trivial to create &#60;code&#62;void nbSerialTx::nbputc(char c)&#60;/code&#62;&#60;br /&#62;
and &#60;code&#62;void nbSerialTx::nbputs(char *s)&#60;/code&#62; using the 'boolean fail' versions.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>robodude666 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7051</link>
			<pubDate>Sun, 30 Oct 2011 15:23:33 +0000</pubDate>
			<dc:creator>robodude666</dc:creator>
			<guid isPermaLink="false">7051@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;I should probably elaborate. It's not blocking in the sense that it prevents the entire program from running, as the current one does. It still does, however, delay the program while the &#60;code&#62;update&#60;/code&#62; routine is being called. Even if that delay is as small as one if statement that returns false. If the statement is true, and it does continue to push data from the buffer then the delay is longer. This overall creates unpredictable slows in the program (they're predictable based on the buad rate used).
&#60;/p&#62;</description>
		</item>
		<item>
			<title>tdc218 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7050</link>
			<pubDate>Sun, 30 Oct 2011 13:16:50 +0000</pubDate>
			<dc:creator>tdc218</dc:creator>
			<guid isPermaLink="false">7050@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Actually it doesn't block (assuming I got the logic right).  Examining the update method will show that the first thing it does is check the TXE bit of the usart status register.  If the usart is NOT ready to take a character, it returns and does nothing.  When the usart is ready for a character, then and only then does it pluck another one out of the ring buffer (assuming there are any to be had) and shove it into the usart.&#60;/p&#62;
&#60;p&#62;One of the assumptions here of course is that our main loop, or wherever we're calling update from, will cycle significantly faster than the characters will send so this has the most utility with slower peripherals.&#60;/p&#62;
&#60;p&#62;On the what to do if the buffer gets full question, the way it's written now the user can specify whether to block on full or discard on full in the init call (defaults to discard).  I also provided the space function that returns how much room is left in the buffer.  But I like your idea about never blocking and returning a bool - that seems like it might be a more elegant solution. I'll have to think about that.&#60;/p&#62;
&#60;p&#62;There are many improvements that could be made, as I said, this is pretty raw code.  Thanks for your comments.
&#60;/p&#62;</description>
		</item>
		<item>
			<title>robodude666 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7047</link>
			<pubDate>Sun, 30 Oct 2011 09:56:25 +0000</pubDate>
			<dc:creator>robodude666</dc:creator>
			<guid isPermaLink="false">7047@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;Very handy! But, it's still technically blocking I think.. it just blocks one character at a time.&#60;/p&#62;
&#60;p&#62;A true non-blocking serial class would use RAM to USART DMA transfers and wouldn't require the &#60;code&#62;update&#60;/code&#62; routine. Once data is available to transmit, a DMA transfer is enabled to push the data out of the buffer. The DMA transfer is handled via hardware, and will not consume any CPU like the &#60;code&#62;update&#60;/code&#62; routine currently does.&#60;/p&#62;
&#60;p&#62;Also, if the class is specifically designed to be a non-blocking serial class, under no circumstance should the class block. To support this, I think that &#60;code&#62;puts&#60;/code&#62; and &#60;code&#62;putc&#60;/code&#62; should return a &#60;code&#62;BOOL&#60;/code&#62;, true or false, as to whether or not the buffer was full before attempting to insert the data. If the buffer cannot support the entire string of data, none of it should be inserted. A false is returned, and the user decides what they want to do. If it's important data to send, they can block themselves and wait for the buffer to relieve itself before successfully attempting to insert the data or move on with the program and do it later.&#60;/p&#62;
&#60;p&#62;-robodude666
&#60;/p&#62;</description>
		</item>
		<item>
			<title>tdc218 on "Non-blocking serial transmit"</title>
			<link>http://forums.leaflabs.com/topic.php?id=1142#post-7046</link>
			<pubDate>Sat, 29 Oct 2011 22:06:29 +0000</pubDate>
			<dc:creator>tdc218</dc:creator>
			<guid isPermaLink="false">7046@http://forums.leaflabs.com/</guid>
			<description>&#60;p&#62;I needed non-blocking serial transmit for a project I'm working on and so I got the following code working tonight.  Eventually it'll turn into a library but for now it's straight out of the incubator - all in one file with it's test program.  The hardest part was understanding how to get ring_buffer working.&#60;/p&#62;
&#60;p&#62;To make it work you have to poll the update() method in loop which means that nothing in your main loop can block either.  A much more elegant solution would be to make it interrupt driven but I'm not ready to climb that mountain yet.&#60;/p&#62;
&#60;p&#62;Use, comment, improve, or flame as desired.    ;)&#60;/p&#62;
&#60;pre&#62;&#60;code&#62;// ********************************************************************************
// begin future nbSerialTX library code
//nbSerialTx.h

/*
 * nbSerialTX - non-blocking Serial Transmit library
 * by &#60;a href=&#34;mailto:tdc218@sbcglobal.net&#34;&#62;tdc218@sbcglobal.net&#60;/a&#62;
 * 2011-Oct-28
 *
 */
#include &#38;quot;ring_buffer.h&#38;quot;
#include &#38;quot;usart.h&#38;quot;

#ifndef _NBSERIALTX_H_
#define _NBSERIALTX_H_

#define NBS_BLOCKONFULL 13
#define NBS_DISCARDONFULL 218

class nbSerialTx
{
  public:
    nbSerialTx(usart_dev *);
    ~nbSerialTx();
    void init(char *, int);
    void init(char *, int, int);
    void update(void);
    void nbputc(char);
    void nbputs(char *);
    int  space(void);

  private:
    usart_reg_map *xregs;
    int            bufsize;
    ring_buffer   rb;
    int            blockflag;
};
#endif

// ********************************************************************************
// nbSerialTx.cpp

//#include &#38;quot;nbSerialTx.h&#38;quot;

nbSerialTx::nbSerialTx(usart_dev *device) {
    this-&#38;gt;xregs = device-&#38;gt;regs;
    this-&#38;gt;bufsize = 0;
//    this-&#38;gt;rb = NULL;              // compiler doesn&#38;#39;t like this
    blockflag = NBS_DISCARDONFULL;
}

nbSerialTx::~nbSerialTx() {
    rb_reset(&#38;amp;rb);
    this-&#38;gt;xregs = (usart_reg_map *)NULL;
    this-&#38;gt;bufsize = 0;
//    this-&#38;gt;rb = NULL;              // compiler doesn&#38;#39;t like this
}

void nbSerialTx::init(char *buffer, int buffer_size) {
    this-&#38;gt;bufsize = buffer_size;
    rb_init(&#38;amp;rb, buffer_size, (uint8 *)buffer);
}

void nbSerialTx::init(char *buffer, int buffer_size, int block) {
    this-&#38;gt;bufsize = buffer_size;
    rb_init(&#38;amp;rb, buffer_size, (uint8 *)buffer);
    blockflag = block;
}

void nbSerialTx::update(void) {

  if (xregs-&#38;gt;SR &#38;amp; USART_SR_TXE)		// if uart transmitter is ready for another character
    if (!(rb_is_empty(&#38;amp;rb)))		// if there is a character to send
       xregs-&#38;gt;DR = rb_remove(&#38;amp;rb);      // then pull it from the buffer and send it
}

//
// Send one character
//    if blockflag is NBS_BLOCKONFULL then the function will block when the buffer gets full
//    otherwise the character will be discarded if the buffer is full
//
void nbSerialTx::nbputc(char c)
{
    if (blockflag == NBS_BLOCKONFULL)
      while (!rb_safe_insert(&#38;amp;rb, (uint8)c));	// wait for buffer to be not full before inserting
    else
      (void)rb_safe_insert(&#38;amp;rb, (uint8)c);		// will only insert if buffer is not full
}

//
// send a string
//
// If you want to print numbers or other fancy stuff, use sprintf, eg:
// #include &#38;lt;stdio.h&#38;gt;
// char buf[SIZE];	// you define SIZE to something larger than the longest string you&#38;#39;re likely to run into
//  sprintf(buf, &#38;quot;x=%04.3f address=%04x\n&#38;quot;, float_var, uint16_var);
//
void nbSerialTx::nbputs(char *s)
{
  char c;

  while ((c = *s++))
    nbputc(c);
}

/*
 * space
 * returns the number of bytes available in the buffer
 *
 */

int nbSerialTx::space(void)
{
  return this-&#38;gt;bufsize - rb_full_count(&#38;amp;rb);
}

// end of future library code
// ********************************************************************************
// begin main
// Assumes a Gravitech SLCD-3 serial LCD on Serial 2
//

#include &#38;lt;stdio.h&#38;gt;

#define MAXMYS2BUF 128

nbSerialTx mys2 = nbSerialTx(USART2);

char mys2buf[MAXMYS2BUF];                    // My serial 2 transmit buffer (wouldn&#38;#39;t need this if we had malloc)
unsigned int sendMillis = 0;                 // store the last time serial test was sent
unsigned int sendInterval = 50;              // interval at which to send serial text

unsigned int previousBlinkMillis = 0;        // will store the last time the LED was updated
unsigned int Blinkinterval = 500;            // interval at which to blink (in milliseconds)

void setup(void)
{
// Set up the built-in LED pin as output:
  pinMode(BOARD_LED_PIN, OUTPUT);
// Seed the random # generator
  pinMode(28, INPUT_ANALOG);
  randomSeed(analogRead(28));

  Serial2.begin(9600);
  Serial2.print(&#38;quot;?f&#38;quot;);    // Gravitech SLCD-3 clear screen command
  delay(100);
  Serial2.print(&#38;quot;?g&#38;quot;);    // beep the LCD&#38;#39;s beeper
  delay(100);
  Serial2.print(&#38;quot;Begin test &#38;quot;);
  Serial2.print(random(100), DEC);  // print a random number so I can tell it really restarted
  Serial2.print(&#38;quot;?n&#38;quot;);        // stupid LCD doesn&#38;#39;t understand real newlines

// initialize
  mys2.init(mys2buf, MAXMYS2BUF);
// send a string to the non-blocking routines
  mys2.nbputs(&#38;quot;Hello,world?n&#38;quot;);

}

void loop(void)
{
    unsigned int currentMillis;
    static unsigned int variation = 0;
    static char spbuf[32];

    currentMillis = millis();
    mys2.update();            // update the non-blocking serial transmit
//
// blink the LED for something to do
//
    if (currentMillis - previousBlinkMillis &#38;gt;= Blinkinterval) {
        // Save the last time you blinked the LED
        previousBlinkMillis = currentMillis;

        // If the LED is off, turn it on, and vice-versa:
        toggleLED();
    }
//
// spit out currentMillis to the serial port at intervals with some random variation
//  The LED should still blink at the correct intervals
//
    if ((currentMillis - sendMillis) &#38;gt;= (sendInterval + variation)) {
      sendMillis = currentMillis;
      variation = 10 - random(20);
      sprintf(spbuf,&#38;quot;%08x?n&#38;quot;, currentMillis);
      mys2.nbputs(spbuf);
    }

}&#60;/code&#62;&#60;/pre&#62;</description>
		</item>

	</channel>
</rss>
