Attempt to read the AD9951 DSP serial output via SSP and \"IRQ driven bit-reading\".

Files at this revision

API Documentation at this revision

Comitter:
AjK
Date:
Tue Jan 18 01:27:57 2011 +0000
Commit message:
0.1 A test failure case!

Changed in this revision

AD9951/AD9951DSPSERIAL.cpp Show annotated file Show diff for this revision Revisions of this file
AD9951/AD9951DSPSERIAL.h Show annotated file Show diff for this revision Revisions of this file
iomacros.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
rx.cpp Show annotated file Show diff for this revision Revisions of this file
tx.cpp Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r e45bbd4486df AD9951/AD9951DSPSERIAL.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AD9951/AD9951DSPSERIAL.cpp	Tue Jan 18 01:27:57 2011 +0000
@@ -0,0 +1,138 @@
+/*
+    Copyright (c) 2011 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#include "AD9951DSPSERIAL.h"
+#include "iomacros.h"
+
+extern Serial pc;
+
+namespace AjK {
+
+class AD9951DSPSERIAL *ad9951dspread_inst = NULL;
+
+extern "C" void _ssp_isr(void) __irq {
+    LED3_ON;
+    if (ad9951dspread_inst) ad9951dspread_inst->ssp_isr();
+}
+
+AD9951DSPSERIAL::AD9951DSPSERIAL()
+{
+    error("No pin definition supplied\n");
+}
+
+AD9951DSPSERIAL::AD9951DSPSERIAL(PinName mosi, PinName miso, PinName sclk, PinName ssel)
+{
+    ad9951dspread_inst = this;
+    LED3_USE;
+    LED4_USE;
+       
+    ssp = NULL;
+    
+    if (mosi == p5 && miso == p6 && sclk == p7 && ssel == p8) {
+        ssp = LPC_SSP1;        
+        pc.printf("  Setting SSP1\n");
+    }
+    else if (mosi == p11 && miso == p12 && sclk == p13 && ssel == p14) {
+        ssp = LPC_SSP0;        
+        pc.printf("  Setting SSP0\n");
+    }
+    else {
+        error("Incorrect pin definition supplied\n");
+    }
+ 
+    init();   
+}
+
+void
+AD9951DSPSERIAL::init(void)
+{
+    _dspread_function = NULL;
+    _dspread_obj      = NULL;
+    _dspread_method   = NULL;
+    
+    if (ssp == LPC_SSP0) {
+        p12_AS_INPUT;
+        LPC_SC->PCONP        |=  (1UL << 21);   // Enable the SSP0 peripheral.
+        LPC_SC->PCLKSEL1     &= ~(3UL << 10);   // Select the clock required for SSP0...
+        LPC_SC->PCLKSEL1     |=  (3UL << 10);   // ... must be at least 12x faster then slave clk coming in.
+        LPC_PINCON->PINSEL0  &= ~(3UL << 30);   // Connect pin SCK0
+        LPC_PINCON->PINSEL0  |=  (2UL << 30);               
+        LPC_PINCON->PINSEL1  &= ~(3UL << 2);    // Connect pin MISO0
+        LPC_PINCON->PINSEL1  |=  (2UL << 2);    
+        LPC_PINCON->PINSEL1  &= ~(3UL << 0);    // Connect pin SSEL0
+        LPC_PINCON->PINSEL1  |=  (2UL << 0);
+        LPC_PINCON->PINSEL1  &= ~(3UL << 4);    // Connect pin MOSI0
+        LPC_PINCON->PINSEL1  |=  (2UL << 4);
+    }
+    
+    if (ssp == LPC_SSP1) {
+        p6_AS_INPUT;
+        LPC_SC->PCONP        |=  (1UL << 10);   // Enable the SSP1 peripheral.
+        LPC_SC->PCLKSEL0     &= ~(3UL << 20);   // Select the clock required for SSP1...
+        LPC_SC->PCLKSEL0     |=  (1UL << 20);   // ... must be at least 12x faster then slave clk coming in.
+        LPC_PINCON->PINSEL0  &= ~(3UL << 14);   // Connect pin SCK1
+        LPC_PINCON->PINSEL0  |=  (2UL << 14);
+        LPC_PINCON->PINSEL0  &= ~(3UL << 16);   // Connect pin MISO1
+        LPC_PINCON->PINSEL0  |=  (2UL << 16);
+        LPC_PINCON->PINSEL0  &= ~(3UL << 12);   // Connect pin SSEL1
+        LPC_PINCON->PINSEL0  |=  (2UL << 12);        
+        LPC_PINCON->PINSEL0  &= ~(3UL << 18);   // Connect pin MOSI1 
+        LPC_PINCON->PINSEL0  |=  (2UL << 18);
+    }
+    
+    // Common setup.
+    //            CPHA=0       CPOL=1    16bit
+    ssp->CR0  = (0UL << 7) | (1UL << 6) | 0xF;
+    ssp->CPSR = 0;
+    ssp->CR1  = (0x3 << 1); 
+    
+    // Enable receiver interrupt.
+    ssp->IMSC = (1UL << 2);
+    
+    if (ssp == LPC_SSP0) {
+        NVIC_SetVector(SSP0_IRQn, (uint32_t)&_ssp_isr);    
+        NVIC_EnableIRQ(SSP0_IRQn);   
+    }
+    
+    if (ssp == LPC_SSP1) {
+        NVIC_SetVector(SSP1_IRQn, (uint32_t)&_ssp_isr);    
+        NVIC_EnableIRQ(SSP1_IRQn);   
+    }       
+}
+
+void
+AD9951DSPSERIAL::ssp_isr(void)
+{
+    uint16_t value;
+    
+    LED4_ON;
+    
+    while (ssp->SR & (1UL << 2)) {
+        value = (uint16_t)(ssp->DR & 0xFFFF);
+        if (_dspread_function != NULL) (*_dspread_function)(value);
+        else {
+            if (_dspread_obj && _dspread_method) (_dspread_obj->*_dspread_method)(value);
+        }
+    }  
+}
+
+}; // namespace AjK ends.
diff -r 000000000000 -r e45bbd4486df AD9951/AD9951DSPSERIAL.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/AD9951/AD9951DSPSERIAL.h	Tue Jan 18 01:27:57 2011 +0000
@@ -0,0 +1,68 @@
+/*
+    Copyright (c) 2011 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+#ifndef AJK_AD9951DSPSERIAL_H
+#define AJK_AD9951DSPSERIAL_H
+
+#include "mbed.h"
+
+namespace AjK {
+
+class AD9951DSPSERIALDummy;
+
+class AD9951DSPSERIAL {
+
+protected:
+
+    LPC_SSP_TypeDef *ssp;
+    
+    // C callback function pointer for to pass read data to.
+    void (*_dspread_function)(uint16_t); 
+    
+    // C++ style callback method pointer for to pass read data to.
+    AD9951DSPSERIALDummy  *_dspread_obj;
+    void (AD9951DSPSERIALDummy::*_dspread_method)(uint16_t);
+    
+    void init(void);
+    
+public:
+
+    AD9951DSPSERIAL();
+    
+    AD9951DSPSERIAL(PinName mosi, PinName miso, PinName sclk, PinName ssel);
+    
+    void ssp_isr(void);
+    
+    void attach_dspread(void (*function)(uint16_t) = 0) { _dspread_function = function; }
+    
+    template<class T> 
+    void attach_dspread(T* item, void (T::*method)(uint16_t)) { 
+        _dspread_obj    = (AD9951DSPSERIALDummy *)item; 
+        _dspread_method = (void (AD9951DSPSERIALDummy::*)(uint16_t))method; 
+    }
+};
+
+}; // namespace AjK ends
+
+using namespace AjK;
+
+#endif
diff -r 000000000000 -r e45bbd4486df iomacros.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/iomacros.h	Tue Jan 18 01:27:57 2011 +0000
@@ -0,0 +1,419 @@
+/*
+    Copyright (c) 2011 Andy Kirkham
+ 
+    Permission is hereby granted, free of charge, to any person obtaining a copy
+    of this software and associated documentation files (the "Software"), to deal
+    in the Software without restriction, including without limitation the rights
+    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the Software is
+    furnished to do so, subject to the following conditions:
+ 
+    The above copyright notice and this permission notice shall be included in
+    all copies or substantial portions of the Software.
+ 
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+    THE SOFTWARE.
+*/
+
+/* Andy's personal pin basher macro file, used mainly for debugging. */
+
+#ifndef IOMACROS_H
+#define IOMACROS_H
+
+#ifndef __LPC17xx_H__
+#include "LPC17xx.h"
+#endif
+
+#define PIN_PULLUP      0UL
+#define PIN_REPEAT      1UL
+#define PIN_NONE        2UL
+#define PIN_PULLDOWN    3UL
+
+/* p5 is P0.9 */
+#define p5_SEL_MASK     ~(3UL << 18)
+#define p5_SET_MASK     (1UL << 9)
+#define p5_CLR_MASK     ~(p5_SET_MASK)
+#define p5_AS_OUTPUT    LPC_PINCON->PINSEL0&=p5_SEL_MASK;LPC_GPIO0->FIODIR|=p5_SET_MASK
+#define p5_AS_INPUT     LPC_GPIO0->FIOMASK &= p5_CLR_MASK; 
+#define p5_SET          LPC_GPIO0->FIOSET = p5_SET_MASK
+#define p5_CLR          LPC_GPIO0->FIOCLR = p5_SET_MASK
+#define p5_IS_SET       (bool)(LPC_GPIO0->FIOPIN & p5_SET_MASK)
+#define p5_IS_CLR       !(p5_IS_SET)
+#define p5_MODE(x)      LPC_PINCON->PINMODE0&=p5_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<18)
+
+/* p6 is P0.8 */
+#define p6_SEL_MASK     ~(3UL << 16)
+#define p6_SET_MASK     (1UL <<  8)
+#define p6_CLR_MASK     ~(p6_SET_MASK)
+#define p6_AS_OUTPUT    LPC_PINCON->PINSEL0&=p6_SEL_MASK;LPC_GPIO0->FIODIR|=p6-SET_MASK
+#define p6_AS_INPUT     LPC_GPIO0->FIOMASK &= p6_CLR_MASK; 
+#define p6_SET          LPC_GPIO0->FIOSET = p6_SET_MASK
+#define p6_CLR          LPC_GPIO0->FIOCLR = p6_SET_MASK
+#define p6_IS_SET       (bool)(LPC_GPIO0->FIOPIN & p6_SET_MASK)
+#define p6_IS_CLR       !(p6_IS_SET)
+#define p6_MODE(x)      LPC_PINCON->PINMODE0&=p6_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<16)    
+
+/* p7 is P0.7 */
+#define p7_SEL_MASK     ~(3UL << 14)
+#define p7_SET_MASK     (1UL <<  7)
+#define p7_CLR_MASK     ~(p7_SET_MASK)
+#define p7_AS_OUTPUT    LPC_PINCON->PINSEL0&=p7_SEL_MASK;LPC_GPIO0->FIODIR|=p7_SET_MASK
+#define p7_AS_INPUT     LPC_GPIO0->FIOMASK &= p7_CLR_MASK; 
+#define p7_SET          LPC_GPIO0->FIOSET = p7_SET_MASK
+#define p7_CLR          LPC_GPIO0->FIOCLR = p7_SET_MASK
+#define p7_IS_SET       (bool)(LPC_GPIO0->FIOPIN & p7_SET_MASK)
+#define p7_IS_CLR       !(p7_IS_SET)
+#define p7_MODE(x)      LPC_PINCON->PINMODE0&=p7_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<14)    
+
+/* p8 is P0.6 */
+#define p8_SEL_MASK     ~(3UL << 12)
+#define p8_SET_MASK     (1UL <<  6)
+#define p8_AS_OUTPUT    LPC_PINCON->PINSEL0&=p8_SEL_MASK;LPC_GPIO0->FIODIR|=p8_SET_MASK
+#define p8_AS_INPUT     LPC_GPIO0->FIOMASK &= p8_CLR_MASK; 
+#define p8_SET          LPC_GPIO0->FIOSET = p8_SET_MASK
+#define p8_CLR          LPC_GPIO0->FIOCLR = p8_SET_MASK
+#define p8_IS_SET       (bool)(LPC_GPIO0->FIOPIN & p8_SET_MASK)
+#define p8_IS_CLR       !(p8_IS_SET)
+#define p8_MODE(x)      LPC_PINCON->PINMODE0&=p8_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<12)    
+
+/* p9 is P0.0 */
+#define p9_SEL_MASK     ~(3UL <<  0)
+#define p9_SET_MASK     (1UL <<  0)
+#define p9_CLR_MASK     ~(p9_SET_MASK)
+#define p9_AS_OUTPUT    LPC_PINCON->PINSEL0&=p9_SEL_MASK;LPC_GPIO0->FIODIR|=p9_SET_MASK
+#define p9_AS_INPUT     LPC_GPIO0->FIOMASK &= p9_CLR_MASK; 
+#define p9_SET          LPC_GPIO0->FIOSET = p9_SET_MASK
+#define p9_CLR          LPC_GPIO0->FIOCLR = p9_SET_MASK
+#define p9_IS_SET       (bool)(LPC_GPIO0->FIOPIN & p9_SET_MASK)
+#define p9_IS_CLR       !(p9_IS_SET)
+#define p9_MODE(x)      LPC_PINCON->PINMODE0&=p9_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<0)    
+
+/* p10 is P0.1 */
+#define p10_SEL_MASK    ~(3UL <<  2)
+#define p10_SET_MASK    (1UL <<  1)
+#define p10_CLR_MASK    ~(p10_SET_MASK)
+#define p10_AS_OUTPUT   LPC_PINCON->PINSEL0&=p10_SEL_MASK;LPC_GPIO0->FIODIR|=p10_SET_MASK
+#define p10_AS_INPUT    LPC_GPIO0->FIOMASK &= p10_CLR_MASK; 
+#define p10_SET         LPC_GPIO0->FIOSET = p10_SET_MASK
+#define p10_CLR         LPC_GPIO0->FIOCLR = p10_SET_MASK
+#define p10_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p10_SET_MASK)
+#define p10_IS_CLR      !(p10_IS_SET)
+#define p10_MODE(x)     LPC_PINCON->PINMODE0&=p10_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<2)
+
+/* p11 is P0.18 */
+#define p11_SEL_MASK    ~(3UL << 4)
+#define p11_SET_MASK    (1UL <<  18)
+#define p11_CLR_MASK    ~(p11_SET_MASK)
+#define p11_AS_OUTPUT   LPC_PINCON->PINSEL1&=p11_SEL_MASK;LPC_GPIO0->FIODIR|=p11_SET_MASK
+#define p11_AS_INPUT    LPC_GPIO0->FIOMASK &= p11_CLR_MASK; 
+#define p11_SET         LPC_GPIO0->FIOSET = p11_SET_MASK
+#define p11_CLR         LPC_GPIO0->FIOCLR = p11_SET_MASK
+#define p11_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p11_SET_MASK)
+#define p11_IS_CLR      !(p11_IS_SET)
+#define p11_MODE(x)     LPC_PINCON->PINMODE1&=p11_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<4)
+
+/* p12 is P0.17 */
+#define p12_SEL_MASK    ~(3UL << 2)
+#define p12_SET_MASK    (1UL << 17)
+#define p12_CLR_MASK    ~(p12_SET_MASK)
+#define p12_AS_OUTPUT   LPC_PINCON->PINSEL1&=p12_SEL_MASK;LPC_GPIO0->FIODIR|=p12_SET_MASK
+#define p12_AS_INPUT    LPC_GPIO0->FIOMASK &= p12_CLR_MASK; 
+#define p12_SET         LPC_GPIO0->FIOSET = p12_SET_MASK
+#define p12_CLR         LPC_GPIO0->FIOCLR = p12_SET_MASK
+#define p12_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p12_SET_MASK)
+#define p12_IS_CLR      !(p12_IS_SET)
+#define p12_MODE(x)     LPC_PINCON->PINMODE1&=p12_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<2)
+
+/* p13 is P0.15 */
+#define p13_SEL_MASK    ~(3UL << 30)
+#define p13_SET_MASK    (1UL << 15)
+#define p13_CLR_MASK    ~(p13_SET_MASK)
+#define p13_AS_OUTPUT   LPC_PINCON->PINSEL0&=p13_SEL_MASK;LPC_GPIO0->FIODIR|=p13_SET_MASK
+#define p13_AS_INPUT    LPC_GPIO0->FIOMASK &= p13_CLR_MASK; 
+#define p13_SET         LPC_GPIO0->FIOSET = p13_SET_MASK
+#define p13_CLR         LPC_GPIO0->FIOCLR = p13_SET_MASK
+#define p13_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p13_SET_MASK)
+#define p13_IS_CLR      !(p13_IS_SET)
+#define p13_MODE(x)     LPC_PINCON->PINMODE0&=p13_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<30)
+
+/* p14 is P0.16 */
+#define p14_SEL_MASK    ~(3UL << 0)
+#define p14_SET_MASK    (1UL << 16)
+#define p14_CLR_MASK    ~(p14_SET_MASK)
+#define p14_AS_OUTPUT   LPC_PINCON->PINSEL1&=p14_SEL_MASK;LPC_GPIO0->FIODIR|=p14_SET_MASK
+#define p14_AS_INPUT    LPC_GPIO0->FIOMASK &= p14_CLR_MASK; 
+#define p14_SET         LPC_GPIO0->FIOSET = p14_SET_MASK
+#define p14_CLR         LPC_GPIO0->FIOCLR = p14_SET_MASK
+#define p14_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p14_SET_MASK)
+#define p14_IS_CLR      !(p14_IS_SET)
+#define p14_MODE(x)     LPC_PINCON->PINMODE1&=p14_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<0)
+
+/* p15 is P0.23 */
+#define p15_SEL_MASK    ~(3UL << 14)
+#define p15_SET_MASK    (1UL << 23)
+#define p15_CLR_MASK    ~(p15_SET_MASK)
+#define p15_AS_OUTPUT   LPC_PINCON->PINSEL1&=p15_SEL_MASK;LPC_GPIO0->FIODIR|=p15_SET_MASK
+#define p15_AS_INPUT    LPC_GPIO0->FIOMASK &= p15_CLR_MASK; 
+#define p15_SET         LPC_GPIO0->FIOSET = p15_SET_MASK
+#define p15_CLR         LPC_GPIO0->FIOCLR = p15_SET_MASK
+#define p15_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p15_SET_MASK)
+#define p15_IS_CLR      !(p15_IS_SET)
+#define p15_MODE(x)     LPC_PINCON->PINMODE1&=p15_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<14)
+
+/* p16 is P0.24 */
+#define p16_SEL_MASK    ~(3UL << 16)
+#define p16_SET_MASK    (1UL <<  24)
+#define p16_CLR_MASK    ~(p16_SET_MASK)
+#define p16_AS_OUTPUT   LPC_PINCON->PINSEL1&=p16_SEL_MASK;LPC_GPIO0->FIODIR|=p16_SET_MASK
+#define p16_AS_INPUT    LPC_GPIO0->FIOMASK &= p16_CLR_MASK; 
+#define p16_SET         LPC_GPIO0->FIOSET = p16_SET_MASK
+#define p16_CLR         LPC_GPIO0->FIOCLR = p16_SET_MASK
+#define p16_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p16_SET_MASK)
+#define p16_IS_CLR      !(p16_IS_SET)
+#define p16_MODE(x)     LPC_PINCON->PINMODE1&=p16_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<16)
+
+/* p17 is P0.25 */
+#define p17_SEL_MASK    ~(3UL <<  18)
+#define p17_SET_MASK    (1UL <<  25)
+#define p17_CLR_MASK    ~(p17_SET_MASK)
+#define p17_AS_OUTPUT   LPC_PINCON->PINSEL1&=p17_SEL_MASK;LPC_GPIO0->FIODIR|=p17_SET_MASK
+#define p17_AS_INPUT    LPC_GPIO0->FIOMASK &= p17_CLR_MASK; 
+#define p17_SET         LPC_GPIO0->FIOSET = p17_SET_MASK
+#define p17_CLR         LPC_GPIO0->FIOCLR = p17_SET_MASK
+#define p17_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p17_SET_MASK)
+#define p17_IS_CLR      !(p17_IS_SET)
+#define p17_MODE(x)     LPC_PINCON->PINMODE1&=p17_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<18)
+
+/* p18 is P0.26 */
+#define p18_SEL_MASK    ~(3UL << 20)
+#define p18_SET_MASK    (1UL << 26)
+#define p18_CLR_MASK    ~(p18_SET_MASK)
+#define p18_AS_OUTPUT   LPC_PINCON->PINSEL1&=p18_SEL_MASK;LPC_GPIO0->FIODIR|=p18_SET_MASK
+#define p18_AS_INPUT    LPC_GPIO0->FIOMASK &= p18_CLR_MASK; 
+#define p18_SET         LPC_GPIO0->FIOSET = p18_SET_MASK
+#define p18_CLR         LPC_GPIO0->FIOCLR = p18_SET_MASK
+#define p18_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p18_SET_MASK)
+#define p18_IS_CLR      !(p18_IS_SET)
+#define p18_MODE(x)     LPC_PINCON->PINMODE1&=p18_SEL_MASK;LPC_PINCON->PINMODE1|=((x&0x3)<<20)
+
+/* p19 is P1.30 */
+#define p19_SEL_MASK    ~(3UL << 28)
+#define p19_SET_MASK    (1UL << 30)
+#define p19_AS_OUTPUT   LPC_PINCON->PINSEL3&=p19_SEL_MASK;LPC_GPIO1->FIODIR|=p19_SET_MASK
+#define p19_AS_INPUT    LPC_GPIO1->FIOMASK &= p19_CLR_MASK; 
+#define p19_SET         LPC_GPIO1->FIOSET = p19_SET_MASK
+#define p19_CLR         LPC_GPIO1->FIOCLR = p19_SET_MASK
+#define p19_IS_SET      (bool)(LPC_GPIO1->FIOPIN & p19_SET_MASK)
+#define p19_IS_CLR      !(p19_IS_SET)
+#define p19_MODE(x)     LPC_PINCON->PINMODE3&=p19_SEL_MASK;LPC_PINCON->PINMODE3|=((x&0x3)<<28)
+
+/* p20 is P1.31 */
+#define p20_SEL_MASK    ~(3UL << 30)
+#define p20_SET_MASK    (1UL << 31)
+#define p20_CLR_MASK    ~(p20_SET_MASK)
+#define p20_AS_OUTPUT   LPC_PINCON->PINSEL3&=p20_SEL_MASK;LPC_GPIO1->FIODIR|=p20_SET_MASK
+#define p20_AS_INPUT    LPC_GPIO1->FIOMASK &= p20_CLR_MASK; 
+#define p20_SET         LPC_GPIO1->FIOSET = p20_SET_MASK
+#define p20_CLR         LPC_GPIO1->FIOCLR = p20_SET_MASK
+#define p20_IS_SET      (bool)(LPC_GPIO1->FIOPIN & p20_SET_MASK)
+#define p20_IS_CLR      !(p20_IS_SET)
+#define p20_MODE(x)     LPC_PINCON->PINMODE3&=p20_SEL_MASK;LPC_PINCON->PINMODE3|=((x&0x3)<<30)
+
+/* p21 is P2.5 */
+#define p21_SEL_MASK    ~(3UL << 10)
+#define p21_SET_MASK    (1UL << 5)
+#define p21_CLR_MASK    ~(p21_SET_MASK)
+#define p21_AS_OUTPUT   LPC_PINCON->PINSEL4&=p21_SEL_MASK;LPC_GPIO2->FIODIR|=p21_SET_MASK
+#define p21_AS_INPUT    LPC_GPIO2->FIOMASK &= p21_CLR_MASK; 
+#define p21_SET         LPC_GPIO2->FIOSET = p21_SET_MASK
+#define p21_CLR         LPC_GPIO2->FIOCLR = p21_SET_MASK
+#define p21_IS_SET      (bool)(LPC_GPIO2->FIOPIN & p21_SET_MASK)
+#define p21_IS_CLR      !(p21_IS_SET)
+#define p21_TOGGLE      p21_IS_SET?p21_CLR:p21_SET
+#define p21_MODE(x)     LPC_PINCON->PINMODE4&=p21_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<10)
+
+/* p22 is P2.4 */
+#define p22_SEL_MASK    ~(3UL << 8)
+#define p22_SET_MASK    (1UL << 4)
+#define p22_CLR_MASK    ~(p22_SET_MASK)
+#define p22_AS_OUTPUT   LPC_PINCON->PINSEL4&=p22_SEL_MASK;LPC_GPIO2->FIODIR|=p22_SET_MASK
+#define p22_AS_INPUT    LPC_GPIO2->FIOMASK &= p22_CLR_MASK; 
+#define p22_SET         LPC_GPIO2->FIOSET = p22_SET_MASK
+#define p22_CLR         LPC_GPIO2->FIOCLR = p22_SET_MASK
+#define p22_IS_SET      (bool)(LPC_GPIO2->FIOPIN & p22_SET_MASK)
+#define p22_IS_CLR      !(p22_IS_SET)
+#define p22_TOGGLE      p22_IS_SET?p22_CLR:p22_SET
+#define p22_MODE(x)     LPC_PINCON->PINMODE4&=p22_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<8)
+
+/* p23 is P2.3 */
+#define p23_SEL_MASK    ~(3UL << 6)
+#define p23_SET_MASK    (1UL << 3)
+#define p23_CLR_MASK    ~(p23_SET_MASK)
+#define p23_AS_OUTPUT   LPC_PINCON->PINSEL4&=p23_SEL_MASK;LPC_GPIO2->FIODIR|=p23_SET_MASK
+#define p23_AS_INPUT    LPC_GPIO2->FIOMASK &= p23_CLR_MASK; 
+#define p23_SET         LPC_GPIO2->FIOSET = p23_SET_MASK
+#define p23_CLR         LPC_GPIO2->FIOCLR = p23_SET_MASK
+#define p23_IS_SET      (bool)(LPC_GPIO2->FIOPIN & p23_SET_MASK)
+#define p23_IS_CLR      !(p23_IS_SET)
+#define p23_TOGGLE      p23_IS_SET?p23_CLR:p23_SET
+#define p23_MODE(x)     LPC_PINCON->PINMODE4&=p23_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<6)
+
+/* p24 is P2.2 */
+#define p24_SEL_MASK    ~(3UL << 4)
+#define p24_SET_MASK    (1UL << 2)
+#define p24_CLR_MASK    ~(p24_SET_MASK)
+#define p24_AS_OUTPUT   LPC_PINCON->PINSEL4&=p24_SEL_MASK;LPC_GPIO2->FIODIR|=p24_SET_MASK
+#define p24_AS_INPUT    LPC_GPIO2->FIOMASK &= p24_CLR_MASK; 
+#define p24_SET         LPC_GPIO2->FIOSET = p24_SET_MASK
+#define p24_CLR         LPC_GPIO2->FIOCLR = p24_SET_MASK
+#define p24_IS_SET      (bool)(LPC_GPIO2->FIOPIN & p24_SET_MASK)
+#define p24_IS_CLR      !(p24_IS_SET)
+#define p24_TOGGLE      p24_IS_SET?p24_CLR:p24_SET
+#define p24_MODE(x)     LPC_PINCON->PINMODE4&=p24_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<4)
+
+/* p25 is P2.1 */
+#define p25_SEL_MASK    ~(3UL << 2)
+#define p25_SET_MASK    (1UL << 1)
+#define p25_CLR_MASK    ~(p25_SET_MASK)
+#define p25_AS_OUTPUT   LPC_PINCON->PINSEL4&=p25_SEL_MASK;LPC_GPIO2->FIODIR|=p25_SET_MASK
+#define p25_AS_INPUT    LPC_GPIO2->FIOMASK &= p25_CLR_MASK; 
+#define p25_SET         LPC_GPIO2->FIOSET = p25_SET_MASK
+#define p25_CLR         LPC_GPIO2->FIOCLR = p25_SET_MASK
+#define p25_IS_SET      (bool)(LPC_GPIO2->FIOPIN & p25_SET_MASK)
+#define p25_IS_CLR      !(p25_IS_SET)
+#define p25_MODE(x)     LPC_PINCON->PINMODE4&=p25_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<2)
+
+/* p26 is P2.0 */
+#define p26_SEL_MASK    ~(3UL << 0)
+#define p26_SET_MASK    (1UL << 0)
+#define p26_CLR_MASK    ~(p26_SET_MASK)
+#define p26_AS_OUTPUT   LPC_PINCON->PINSEL4&=p26_SEL_MASK;LPC_GPIO2->FIODIR|=p26_SET_MASK
+#define p26_AS_INPUT    LPC_GPIO2->FIOMASK &= p26_CLR_MASK; 
+#define p26_SET         LPC_GPIO2->FIOSET = p26_SET_MASK
+#define p26_CLR         LPC_GPIO2->FIOCLR = p26_SET_MASK
+#define p26_IS_SET      (bool)(LPC_GPIO2->FIOPIN & p26_SET_MASK)
+#define p26_IS_CLR      !(p26_IS_SET)
+#define p26_MODE(x)     LPC_PINCON->PINMODE4&=p26_SEL_MASK;LPC_PINCON->PINMODE4|=((x&0x3)<<0)
+
+/* p27 is P0.11 */
+#define p27_SEL_MASK    ~(3UL << 22)
+#define p27_SET_MASK    (1UL << 11)
+#define p27_CLR_MASK    ~(p27_SET_MASK)
+#define p27_AS_OUTPUT   LPC_PINCON->PINSEL0&=p27_SEL_MASK;LPC_GPIO0->FIODIR|=p27_SET_MASK
+#define p27_AS_INPUT    LPC_GPIO0->FIOMASK &= p27_CLR_MASK; 
+#define p27_SET         LPC_GPIO0->FIOSET = p27_SET_MASK
+#define p27_CLR         LPC_GPIO0->FIOCLR = p27_SET_MASK
+#define p27_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p27_SET_MASK)
+#define p27_IS_CLR      !(p27_IS_SET)
+#define p27_MODE(x)     LPC_PINCON->PINMODE0&=p27_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<22)
+
+/* p28 is P0.10 */
+#define p28_SEL_MASK    ~(3UL << 20)
+#define p28_SET_MASK    (1UL <<  10)
+#define p28_CLR_MASK    ~(p28_SET_MASK)
+#define p28_AS_OUTPUT   LPC_PINCON->PINSEL0&=p28_SEL_MASK;LPC_GPIO0->FIODIR|=p28_SET_MASK
+#define p28_AS_INPUT    LPC_GPIO0->FIOMASK &= p28_CLR_MASK; 
+#define p28_SET         LPC_GPIO0->FIOSET = p28_SET_MASK
+#define p28_CLR         LPC_GPIO0->FIOCLR = p28_SET_MASK
+#define p28_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p28_SET_MASK)
+#define p28_IS_CLR      !(p28_IS_SET)
+#define p28_MODE(x)     LPC_PINCON->PINMODE0&=p28_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<20)
+
+/* p29 is P0.5 */
+#define p29_SEL_MASK    ~(3UL << 10)
+#define p29_SET_MASK    (1UL << 5)
+#define p29_CLR_MASK    ~(p29_SET_MASK)
+#define p29_AS_OUTPUT   LPC_PINCON->PINSEL0&=p29_SEL_MASK;LPC_GPIO0->FIODIR|=p29_SET_MASK
+#define p29_AS_INPUT    LPC_GPIO0->FIOMASK &= p29_CLR_MASK; 
+#define p29_SET         LPC_GPIO0->FIOSET = p29_SET_MASK
+#define p29_CLR         LPC_GPIO0->FIOCLR = p29_SET_MASK
+#define p29_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p29_SET_MASK)
+#define p29_IS_CLR      !(p29_IS_SET)
+#define p29_TOGGLE      p29_IS_SET?p29_CLR:p29_SET
+#define p29_MODE(x)     LPC_PINCON->PINMODE0&=p29_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<10)
+
+/* p30 is P0.4 */
+#define p30_SEL_MASK    ~(3UL << 8)
+#define p30_SET_MASK    (1UL << 4)
+#define p30_CLR_MASK    ~(p30_SET_MASK)
+#define p30_AS_OUTPUT   LPC_PINCON->PINSEL0&=p30_SEL_MASK;LPC_GPIO0->FIODIR|=p30_SET_MASK
+#define p30_AS_INPUT    LPC_GPIO0->FIOMASK &= p30_CLR_MASK; 
+#define p30_SET         LPC_GPIO0->FIOSET = p30_SET_MASK
+#define p30_CLR         LPC_GPIO0->FIOCLR = p30_SET_MASK
+#define p30_IS_SET      (bool)(LPC_GPIO0->FIOPIN & p30_SET_MASK)
+#define p30_IS_CLR      !(p30_IS_SET)
+#define p30_MODE(x)     LPC_PINCON->PINMODE0&=p30_SEL_MASK;LPC_PINCON->PINMODE0|=((x&0x3)<<8)
+
+/* The following definitions are for the four Mbed LEDs.
+    LED1 = P1.18
+    LED2 = P1.20
+    LED3 = P1.21
+    LED4 = P1.23 */
+
+#define P1_18_SEL_MASK  ~(3UL << 4)
+#define P1_18_SET_MASK  (1UL << 18)
+#define P1_18_CLR_MASK  ~(P1_18_SET_MASK)
+#define P1_18_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_18_SEL_MASK;LPC_GPIO1->FIODIR|=P1_18_SET_MASK
+#define P1_18_AS_INPUT  LPC_GPIO1->FIOMASK &= P1_18_CLR_MASK; 
+#define P1_18_SET       LPC_GPIO1->FIOSET = P1_18_SET_MASK
+#define P1_18_CLR       LPC_GPIO1->FIOCLR = P1_18_SET_MASK
+#define P1_18_IS_SET    (bool)(LPC_GPIO1->FIOPIN & P1_18_SET_MASK)
+#define P1_18_IS_CLR    !(P1_18_IS_SET)
+#define LED1_USE        P1_18_AS_OUTPUT;P1_18_AS_INPUT
+#define LED1_ON         P1_18_SET
+#define LED1_OFF        P1_18_CLR
+#define LED1_IS_ON      P1_18_IS_SET
+#define LED1_TOGGLE     P1_18_IS_SET?LED1_OFF:LED1_ON
+
+#define P1_20_SEL_MASK  ~(3UL << 8)
+#define P1_20_SET_MASK  (1UL << 20)
+#define P1_20_CLR_MASK  ~(P1_20_SET_MASK)
+#define P1_20_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_20_SEL_MASK;LPC_GPIO1->FIODIR|=P1_20_SET_MASK
+#define P1_20_AS_INPUT  LPC_GPIO1->FIOMASK &= P1_20_CLR_MASK; 
+#define P1_20_SET       LPC_GPIO1->FIOSET = P1_20_SET_MASK
+#define P1_20_CLR       LPC_GPIO1->FIOCLR = P1_20_SET_MASK
+#define P1_20_IS_SET    (bool)(LPC_GPIO1->FIOPIN & P1_20_SET_MASK)
+#define P1_20_IS_CLR    !(P1_20_IS_SET)    
+#define LED2_USE        P1_20_AS_OUTPUT;P1_20_AS_INPUT
+#define LED2_ON         P1_20_SET
+#define LED2_OFF        P1_20_CLR
+#define LED2_IS_ON      P1_20_IS_SET
+#define LED2_TOGGLE     P1_20_IS_SET?LED2_OFF:LED2_ON
+
+#define P1_21_SEL_MASK  ~(3UL << 10)
+#define P1_21_SET_MASK  (1UL << 21)
+#define P1_21_CLR_MASK  ~(P1_21_SET_MASK)
+#define P1_21_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_21_SEL_MASK;LPC_GPIO1->FIODIR|=P1_21_SET_MASK
+#define P1_21_AS_INPUT  LPC_GPIO1->FIOMASK &= P1_21_CLR_MASK; 
+#define P1_21_SET       LPC_GPIO1->FIOSET = P1_21_SET_MASK
+#define P1_21_CLR       LPC_GPIO1->FIOCLR = P1_21_SET_MASK
+#define P1_21_IS_SET    (bool)(LPC_GPIO1->FIOPIN & P1_21_SET_MASK)
+#define P1_21_IS_CLR    !(P1_21_IS_SET)
+#define LED3_USE        P1_21_AS_OUTPUT;P1_21_AS_INPUT
+#define LED3_ON         P1_21_SET
+#define LED3_OFF        P1_21_CLR
+#define LED3_IS_ON      P1_21_IS_SET
+#define LED3_TOGGLE     P1_21_IS_SET?LED3_OFF:LED3_ON
+
+#define P1_23_SEL_MASK  ~(3UL << 14)
+#define P1_23_SET_MASK  (1UL << 23)
+#define P1_23_CLR_MASK  ~(P1_23_SET_MASK)
+#define P1_23_AS_OUTPUT LPC_PINCON->PINSEL3&=P1_23_SEL_MASK;LPC_GPIO1->FIODIR|=P1_23_SET_MASK
+#define P1_23_AS_INPUT  LPC_GPIO1->FIOMASK &= P1_23_CLR_MASK; 
+#define P1_23_SET       LPC_GPIO1->FIOSET = P1_23_SET_MASK
+#define P1_23_CLR       LPC_GPIO1->FIOCLR = P1_23_SET_MASK
+#define P1_23_IS_SET    (bool)(LPC_GPIO1->FIOPIN & P1_23_SET_MASK)
+#define P1_23_IS_CLR    !(P1_23_IS_SET)    
+#define LED4_USE        P1_23_AS_OUTPUT;P1_23_AS_INPUT
+#define LED4_ON         P1_23_SET
+#define LED4_OFF        P1_23_CLR
+#define LED4_IS_ON      P1_23_IS_SET
+#define LED4_TOGGLE     P1_23_IS_SET?LED4_OFF:LED4_ON
+
+#endif
+
diff -r 000000000000 -r e45bbd4486df main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Tue Jan 18 01:27:57 2011 +0000
@@ -0,0 +1,36 @@
+
+#include "mbed.h"
+#include "iomacros.h"
+
+DigitalOut led1(LED1);
+Serial pc(USBTX, USBRX);
+
+// The two main functions, call one or the other
+// depending on P20, one Mbed or the other.
+void tx(Serial *, DigitalOut *);
+void rx(Serial *, DigitalOut *);
+
+int main() {
+
+    p20_AS_INPUT;
+    p20_MODE(PIN_PULLUP);
+    
+    pc.baud(115200);
+    
+    if (p20_IS_SET) tx(&pc, &led1); // This is the sending Mbed that creates the waveforms
+    else            rx(&pc, &led1); // This is the receiving Mbed that tries to read it.
+    
+    // Note, I used two Mbeds. I could just use one but I didn't want the
+    // software creating the waveforms to steal CPU time. I wanted the receiver
+    // to have all available CPU time it needed. End result, no where enough
+    // with a software soluttion and the SSP failed totally by missing the first bit.
+    
+    // With the software solution I did manage to read the data but only to about
+    // 500kHz. The Mbed libs are known to be slow so I could have tried using direct
+    // peripheral usage. But I know from experience that even doing that I would prob
+    // get upto about maybe 1.5MHz. No where near the 6.5MHz needed to read the 
+    // AD9951 DSP serial output. Shame on Maxim for having a, err, dumb ass serial
+    // protocol!
+
+    
+}
diff -r 000000000000 -r e45bbd4486df mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Tue Jan 18 01:27:57 2011 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/e2ac27c8e93e
diff -r 000000000000 -r e45bbd4486df rx.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/rx.cpp	Tue Jan 18 01:27:57 2011 +0000
@@ -0,0 +1,88 @@
+
+#include "mbed.h"
+
+bool doPrint;
+InterruptIn ad9951_clk(p13);
+InterruptIn ad9951_sync(p14);
+DigitalIn   ad9951_data(p11);
+
+int bitCount, bitCountR;
+uint16_t dsp_value, dsp_value_shift;
+
+void ad9951_sync_rise(void) {
+    dsp_value = dsp_value_shift;
+    dsp_value_shift = 0;
+    bitCountR = bitCount;
+    bitCount = 0;
+    doPrint = true;
+}
+
+void ad9951_clk_fall(void) {
+    bitCount++;
+    dsp_value_shift = dsp_value_shift << 1;
+    dsp_value_shift |= ad9951_data == 1 ? 1 : 0;    
+}
+
+void rx(Serial *pc, DigitalOut *led1) {
+    doPrint = false;
+    dsp_value = dsp_value_shift = 0;
+    bitCount = 0;
+    
+    pc->printf("Starting MBED as the receiver...\n");
+    
+    ad9951_sync.rise(&ad9951_sync_rise);
+    ad9951_clk.fall(&ad9951_clk_fall);
+    
+    while(1) {
+        if (doPrint) {
+            
+            pc->printf("Got %04x from %d\n", dsp_value, bitCountR);
+            doPrint = false;
+        }
+    }
+}
+
+#ifdef NO_COMPILE
+
+#include "AD9951DSPSERIAL.h"
+
+Ticker led1Flasher;
+DigitalOut *pLed1;
+AD9951DSPSERIAL *myDevice;
+
+bool irqCalled;
+uint16_t dsp_value;
+
+void flashLed1(void) {
+    pLed1->write( !pLed1->read() );
+}
+
+void dspReadCallback(uint16_t value) {
+    if (!irqCalled) {
+        dsp_value = value;
+        irqCalled = true;
+    }
+}
+
+void rx(Serial *pc, DigitalOut *led1) {
+    pLed1 = led1;
+    
+    irqCalled = false;
+    
+    pc->printf("Starting MBED as the receiver...\n");
+    
+    myDevice = new AD9951DSPSERIAL(p11, p12, p13, p14);
+    
+    led1Flasher.attach(&flashLed1, 0.1);
+    
+    myDevice->attach_dspread(&dspReadCallback);
+    
+    while(1) {
+        if (irqCalled) {
+            pc->printf("Got %04x\n", dsp_value);
+            irqCalled = false;
+        }
+    }
+}
+
+#endif
diff -r 000000000000 -r e45bbd4486df tx.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tx.cpp	Tue Jan 18 01:27:57 2011 +0000
@@ -0,0 +1,66 @@
+
+#include "mbed.h"
+#include "iomacros.h"
+
+// Works with 10 (ie CLK cycle time 20us)
+// but fails with 5 (10us). No where even 
+// close to 6.5MHz !!
+#define DELAY 10
+
+#define SYNC_1  p23_SET
+#define SYNC_0  p23_CLR
+#define CLK_1   p22_SET
+#define CLK_0   p22_CLR
+#define DATA_1  p21_SET
+#define DATA_0  p21_CLR
+
+void tx(Serial *pc, DigitalOut *led1) {
+    uint16_t counter = 0xAAAA, mask;
+    
+    pc->printf("Starting MBED as the sender...\n");
+    
+    p21_AS_OUTPUT;  // SERDATA
+    p22_AS_OUTPUT;  // CLK
+    p23_AS_OUTPUT;  // SYNC
+
+    p21_CLR;
+    p22_CLR;
+    p23_SET;
+
+    while(1) {
+        mask = 0x8000;
+        for (int i = 0; i < 16; i++) {
+            
+            if (i == 0) {
+                SYNC_1;                
+            }
+            else {
+                SYNC_0;                
+            }
+            
+            if ((counter & mask) != 0) DATA_1;
+            else                       DATA_0;
+            
+            CLK_1;
+            wait_us(DELAY);
+            
+            CLK_0;            
+            wait_us(DELAY);
+            
+            mask = mask >> 1;
+        }
+    
+        // The above loop recreates Michele's waveform as shown on
+        // http://mbed.org/forum/helloworld/topic/1674
+        
+        // However, to coax the receiving SSP on the other Mbed
+        // the following extra clk is needed. Even then the 16bit
+        // value read isn't 0xAAAA but 0x5554 as the first bit is sent
+        // while SYNC is asserted. Thus the "other end" doesn't see bit0
+        // and misses the last bit.
+        
+        //CLK_1; wait_us(DELAY); CLK_0; wait_us(DELAY);
+        
+        //counter++;
+    }    
+}