20081112 Slider Control

Adding a slider to the TCPIP STack application and passing the value back to the hardware..  with the expectation that we will be adding multiple sliders later.. to control additional hardware..  This exercise is to get the slider value into the hardware and back out again..

Note that any Microchip TCPIP Stack compatible hardware platform will work with this.. 


Step 1: get the slider onto an embedded web page

- Decided to use Yahoo User Interface library after googling 'html slider control' as it looks pretty comprehensive!.. (storing YUI build files on an external website ..)..

Start point: Copied 'C:\Microchip Solutions\TCPIP Demo App\WebPages2' as 'C:\Microchip Solutions\TCPIP Demo App\WebPages2 - Mine with YUI' 

- Yahoo demo page 'slider-simple_clean.htm' copied to above directory, edited for all src references and added the header bits into header.inc to be the YUI files on the remote xxx.com as well as the one local reference in slider-simple_clean

- header.inc added the header bits from Yahoo demo page 'slider-simple_clean.htm' (we uploaded the YUI library build files to xxx.com/_yui/ previously and referring to it remotely because no room on my hardware 32k SPI module):

<link rel="stylesheet" type="text/css" href="http://xxx.com/_yui/build/fonts/fonts-min.css" />
<link rel="stylesheet" type="text/css" href="http://xxx.com.com/_yui/build/slider/assets/skins/sam/slider.css" />
<script type="text/javascript" src="http://xxx.com.com/_yui/build/yahoo-dom-event/yahoo-dom-event.js"></script>
<script type="text/javascript" src="http://xxx.com.com/_yui/build/animation/animation-min.js"></script>
<script type="text/javascript" src="http://xxx.com.com/_yui/build/dragdrop/dragdrop-min.js"></script>
<script type="text/javascript" src="http://xxx.com.com/_yui/build/slider/slider-min.js"></script>

- new file sliders.cgi (used to return the response)

~slider1~

added to status.xml (so we can include slider 1 on the index page)

<response>
<led0>~led(0)~</led0>
<led1>~led(1)~</led1>
<led2>~led(2)~</led2>
<led3>~led(3)~</led3>
<btn0>~btn(0)~</btn0>
<btn1>~btn(1)~</btn1>
<btn2>~btn(2)~</btn2>
<btn3>~btn(3)~</btn3>
<pot0>~pot~</pot0>
<slider1>~slider1~</slider1>
</response>

renamed 'slider-simple_clean.htm as pwm2.htm (as first iteration will be controlling a DC motor using PWM on CCP2) and edited it.  Slider is 0-200 pixels and scales as 0-100 (for a PWM % control).  We also updated one of the demo buttons as an emergency stop button and removed the other.

 ~inc:header.inc~
 
<div id="content" class="yui-skin-sam">
 
<h1>&nbsp;</h1>
 
<h1>PWM motor control, varies the % pulse width exactly</h1>
 
<div class="exampleIntro">
 <p>~slider1~</p>
<ul>
   
</div>
 
<div id="slider-bg" class="yui-v-slider" tabindex="-1" title="Slider">
 <div id="slider-thumb" class="yui-slider-thumb"><img src="http://xxx.com/_yui/build/slider/assets/thumb-bar.gif"></div>
</div>
 
<p>Pixel value: <span id="slider-value">0</span></p>
 
<p>Converted value:
<input autocomplete="off" id="slider-converted-value" type="text" value="0" size="4" maxlength="4" />
</p>
 
<!--We'll use these to trigger interactions with the Slider API -->
<button id="ALLSTOP">Emergency STOP</button>

<script type="text/javascript">
(function() {
 var Event = YAHOO.util.Event,
 Dom = YAHOO.util.Dom,
 lang = YAHOO.lang,
 slider,
 bg="slider-bg", thumb="slider-thumb",
 valuearea="slider-value", textfield="slider-converted-value"

 // The slider can move 0 pixels up
 var topConstraint = 0;

 // The slider can move 200 pixels down
 var bottomConstraint = 200;

 // Custom scale factor for converting the pixel offset into a real value
 var scaleFactor = 0.5;

 // The amount the slider moves when the value is changed with the arrow
 // keys
 var keyIncrement = 1;

 Event.onDOMReady(function() {

 slider = YAHOO.widget.Slider.getVertSlider(bg,
 thumb, topConstraint, bottomConstraint);

 slider.getRealValue = function() {
 return Math.round(this.getValue() * scaleFactor);
 }

 slider.subscribe("change", function(offsetFromStart) {

 var valnode = Dom.get(valuearea);
 var fld = Dom.get(textfield);

 // Display the pixel value of the control
 valnode.innerHTML = offsetFromStart;

 // use the scale factor to convert the pixel offset into a real
 // value
 var actualValue = slider.getRealValue();

 // update the text box with the actual value
 fld.value = actualValue;

 // Update the title attribute on the background. This helps assistive
 // technology to communicate the state change
 Dom.get(bg).title = "slider value = " + actualValue;

 });

 slider.subscribe("slideStart", function() {
 YAHOO.log("slideStart fired", "warn");
 });

 slider.subscribe("slideEnd", function() {
      newAJAXCommand('sliders.cgi?slider1=' + slider.getRealValue());
 });

 // set an initial value
 slider.setValue(0);

 // Listen for keystrokes on the form field that displays the
 // control's value. While not provided by default, having a
 // form field with the slider is a good way to help keep your
 // application accessible.
 Event.on(textfield, "keydown", function(e) {

 // set the value when the 'return' key is detected
 if (Event.getCharCode(e) === 13) {
 var v = parseFloat(this.value, 10);
 v = (lang.isNumber(v)) ? v : 0;

 // convert the real value into a pixel offset
 slider.setValue(Math.round(v/scaleFactor));
 }
 });
 // Use setValue to reset the value to white:
 Event.on("ALLSTOP", "click", function(e) {
 slider.setValue(0, false);
//false here means to animate if possible
 });
 });
})();
</script>

~inc:footer.inc~

 - MPFS2 Build & Upload, slider works on the served up page.. (Removed a few of the other pages so the the MPFS build utility would manage to fit it into the 32k available).  Note that MPFS2 reminded us that there were new dynamic variables (~slider1~) so we would need to rebuild our firmware..

Step 2: Process the value on the server and also return it..

Lots of random info here: http://forum.microchip.com/tm.aspx?m=346502&mpage=1&key=ajax&#348031 a shame they dont post the complete sucessful bits after.. so we will guess with a bit of trial and error.

edited CustomHTTPApp.c

- added a static declare at the top: 'static WORD slider1 = 0;'

- copied the '// If it's the LED updater file' below to a new section:

 Copied thisimmediately after as this:
 // If it's the LED updater file
 else if(!memcmppgm2ram(filename, "leds.cgi", 8))
 {
  // Determine which LED to toggle
  ptr = HTTPGetROMArg(curHTTP.data, (ROM BYTE *)"led");
  
  // Toggle the specified LED
  switch(*ptr) {
   case '1':
    LED1_IO ^= 1;
    break;
   case '2':
    LED2_IO ^= 1;
    break;
   case '3':
    LED3_IO ^= 1;
    break;
   case '4':
    LED4_IO ^= 1;
    break;
   case '5':
    LED5_IO ^= 1;
    break;
   case '6':
    LED6_IO ^= 1;
    break;
   case '7':
    LED7_IO ^= 1;
    break;
  }
  // <- ADDED HERE
 } 
 // If it's the SLIDER updater file
 else if(!memcmppgm2ram(filename, "sliders.cgi", 11))
 {
  ptr = HTTPGetROMArg(curHTTP.data, (ROM BYTE *)"slider1");
  if(ptr)
  {
  slider1 = atoi(ptr);
  }

Also added an HTTPPrint function so I can display the setting as a dynamic variable on pwm2.htm (the '~slider1~' entry).

void HTTPPrint_slider1(void)
{
 BYTE sliderstring[8];
 // Print the value
    uitoa(slider1, (BYTE*)sliderstring);
    TCPPutString(sktHTTP, sliderstring);
}

Did a Project -> Build All and it works.