ThinkClamp Bluetooth project ceased

I’ve decided to stop working on the ThinkPad keyboard adapter with Bluetooth support. It’s taking too much time and the work is repetitive. I’ll probably just add UART to my USB board, add in a LiPo charger and modify the firmware a bit. It’s possibly not going to be energy efficient compared to using interrupts on the keyboard inputs and the TrackPoint clock line.

Also, prices for MSP430 parts are jacking up. It’s simply not economical to use them anymore. I’ll switch to ARM Cortex-M0+, like Freescale KL2x series.

Thus, here’s the schematic to the ThinkClamp PCB v0.8. I hope it helps you with your future endeavor with building a keyboard & TrackPoint adapter.

As for folks who would want to build a case, I’ve made a 3D model of the ThinkPad T60 keyboard: Grabcad.

ThinkClamp – short project update

Finally got some spare time yesterday to solder the new PCB revision and it works well, some better than anticipated. I’ve found one or two PCB errors. Nothing major though, it’s all working well enough.

I decided not to solder on the reset buttons as a slide between the ON and OFF positions of the slide switch would effectively reset the entire board.

Soldered board with MSP430F5502 and HM-10

Soldered board with MSP430F5502 and HM-10

Now it’s time for some programming. With a USB-enabled microcontroller, this board would eventually support both USB and Bluetooth functionality, preferably with the same firmware flashed. I’ve decided to use the HM-10 with my custom firmware instead of using a RN42-HID module so I can further improve the firmware.

Update: There might be a minor problem with the LiPo charger in which the battery voltage may jitter when a battery is not connected. This caused a bit of a random enumeration/disconnection problem. However, if a battery is connected to the battery output pins, the board seems to work fine. The USB microcontroller enumerates with no problems at all. For now, I’ve soldered on a single-cell battery pack so that I may get on to write the firmware.

Krisp and their incredible glossy photo paper

Krisp’s glossy photo paper for inkjet printers is amazing for PCB toner transfer. It takes toner superbly well from a Xerox laser printer and with no soaking required, the paper can be easily peeled off, leaving toner sitting perfectly still on the PCB copper surface. Here’s the proof:

Great print

Great print

Amazing transfer

Amazing transfer, well except for that tiny bit on the bottom left

Trasferred PCB, it looks much sharper on camera

Etched PCB, it looks much sharper on camera

It has been wasteful to use an A4 piece of paper on so little printing area so imagine the if multiple PCB designs are panelized, imagine all the designs that can fit on an A4 and save so much time not soaking and removing the paper layer-by-layer.

This might be old news, but as the site description “The archive of things that are worth posting” dictates, this post is worth posting.

CC254x HID Project – Name changing feature added

After many weeks working on this particular feature, I have finally succeeded. Strangely enough, the solution is so simple, making all the other ways I have thought of seems dumb and unnecessary.

The name is stored in CC2540/1’s non-volatile (NV) memory. Along with the name, its CRC checksum and length are stored in separate NV memory slots as well. Upon start-up, the name and its CRC value is retrieved from the NV memory. A new CRC value is generated from the stored name and compared with the stored CRC value. If the two CRC values matches, the device will go on and set this stored name as the scan response data string and the device’s name. Otherwise, it will use the default names.

Before today, I have been trying the idea of dynamically allocating an array and filling it with appropriate elements to make up a new scan response. This approach has been fruitless. Then I realized, why not use the static scan response variable that is going to be available every time the device starts up and modify its elements instead. This new approach works flawlessly (after only a few tests).

The code should be pushed and available on Git (one of those repositories) soon enough. However, for future debugging, these are the relevant sections to this feature:

0. Local variables and constants

#define SNV_ID_DEVICE_NAME              0x80
#define SNV_ID_DEVICE_NAME_LENGTH       0x81
#define SNV_ID_DEVICE_NAME_CRC          0x82

uint8 *device_name_crc;
uint8 *device_name;
uint8 *device_name_length;
    
// GAP Profile - Name attribute for SCAN RSP data - Name shown up when scanned
static uint8 default_scanData[] =
{
  0x15,                             // length of this data => (name's size = 20 bytes) + 1
  GAP_ADTYPE_LOCAL_NAME_COMPLETE,   // AD Type = Complete local name
  'H',
  'I',
  'D',
  ' ',
  'K',
  'e',
  'y',
  'b',
  'o',
  'a',
  'r',
  'd',
  ' ',
  '&',
  ' ',
  'M',
  'o',
  'u',
  's',
  'e'
};

1. Local functions

//Pololu's CRC functions with minimal changes
uint8 CRCPoly = 0x89;  // the value of our CRC-7 polynomial
uint8 CRCTable[256];

void GenerateCRCTable()
{
    int i, j;
 
    // generate a table value for all 256 possible byte values
    for (i = 0; i < 256; i++)
    {
        CRCTable[i] = (i & 0x80) ? i ^ CRCPoly : i;
        for (j = 1; j < 8; j++)
        {
            CRCTable[i] <<= 1;
            if (CRCTable[i] & 0x80)
                CRCTable[i] ^= CRCPoly;
        }
    }
}
 
 
// adds a message byte to the current CRC-7 to get a the new CRC-7
uint8 CRCAdd(uint8 CRC, uint8 message_byte)
{
    return CRCTable[(CRC << 1) ^ message_byte];
}
 
 
// returns the CRC-7 for a message of "length" bytes
uint8 getCRC(uint8 message[], uint8 length)
{
    uint8 i;
    uint8 CRC = 0;
 
    for (i = 0; i < length; i++)
        CRC = CRCAdd(CRC, message[i]);
 
    return CRC;
}

3. Initialization in hidKbdMouse.c

void HidKbdMouse_Init( uint8 task_id )
{
  setupUART();
  GenerateCRCTable();
//......

4. Name checking during initlization

//about line 354 in source code
if(*device_name_crc != getCRC(device_name, *device_name_length)) {
      printf("Using default scan response name\r\n");
      GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( default_scanData ), default_scanData );
    } else {      
      //make changes directly to the default_scanData. Since this variable is set at start-up, it should not matter
      uint8 len = *device_name_length;
      uint8 default_name_length = default_scanData[0];
      default_scanData[0] = len + 1;
      uint8 i;
      for(i = 0; i < len; i++) {
        default_scanData[i+2] = device_name[i];
      }      
      GAPRole_SetParameter( GAPROLE_SCAN_RSP_DATA, sizeof ( default_scanData ), default_scanData );
    }

//...
//about line 377 in source code
 if(*device_name_crc != getCRC(device_name, *device_name_length)) {
    GGS_SetParameter( GGS_DEVICE_NAME_ATT, GAP_DEVICE_NAME_LEN, (void *) attDeviceName );
  } else {
    GGS_SetParameter( GGS_DEVICE_NAME_ATT, *device_name_length + 1, (void *) device_name );
  }

5. UART name changing section

//...
else if((rxBuffer[1] == 'N') && (rxBuffer[2] == ',')) {
      uint8 i;
      uint8 deviceNewName[20];
      uint8 deviceNewNameLength;
      uint8 deviceNewNameCRC;
      
      deviceNewNameLength = rxBufferIndex-3;
      if(deviceNewNameLength > 20) {
        printf("Name exceeds permitted length\r\n");
      } else {
        for(i = 3; i < rxBufferIndex; i++) {
          deviceNewName[i-3] = rxBuffer[i];
        }   
        deviceNewName[deviceNewNameLength] = '\0';
        deviceNewNameCRC = getCRC(deviceNewName, deviceNewNameLength);

        osal_snv_write(SNV_ID_DEVICE_NAME, 20, deviceNewName);
        osal_snv_write(SNV_ID_DEVICE_NAME_LENGTH, 1, &deviceNewNameLength);
        osal_snv_write(SNV_ID_DEVICE_NAME_CRC, 1, &deviceNewNameCRC);
        printf("Name is being set, reset to set new name\r\n");
      }
  • To change the device’s scan response data and device’s name, first it must be put into CMD mode by sending 3’s @, ie. @@@
  • Then, the name can be set to be stored with SN,<value> where is the new name and it must be less than 20 characters long.
  • To see changes, the device needs to be restarted with S,R.

Ceasing development for CC254x BLE HID project

Windows 7 does not have any support for Bluetooth Low Energy stack. There are 3rd party commercial products, but who would want to install additional costly software just to use a keyboard/mouse combo. I do not have a Windows 8 machine and because of this particular reason, a few features of the HID stack cannot be developed and tested, such as LED reports, remote wake-up, etc. Although I have a touch-only tablet that supports BLE, using it for testing is not enjoyable and it cannot be tested for mouse feature.

The only do-able feature left to be implemented is the name change via serial. After this feature is implemented, the development of the project will be ceased.

Plans for ThinkClamp v0.7

ThinkClamp Pre-Ultimatum

In version 0.7, the ThinkClamp hardware and firmware will be completely re-designed.

It will use an inverter RC circuit to reset the TrackPoint using the clock line instead of a pin. This opens up the UART port which allows the MCU to talk to various Bluetooth modules. If this does not work well, the user will have the option to connect the RX line back to the TrackPoint’s reset line like before. Bluetooth communication should not be interfered as many of these Bluetooth modules mostly listens for commands instead of sending out any. Bluetooth modules that can be soldered onto the board includes HC-05, HC-06 and HM-10, in which HID firmware can be programmed.

The board will feature a single cell LiPo charging station with JST 2.0mm connector, which is the battery connector for many remote controlled airplanes and helicopter batteries. Just go to a model shop and try out the batteries until one fits. LEDs are included on-board to indicate whether if battery charging status. Charging will be done through connecting the board to a power source through the micro-USB connector. If a battery is not used, the header next to the BSL button may be connected to allow 5V from the USB to flow straight to the circuit.

The microcontroller is chosen to be compatible with a MSP430F5510 and MSP430F5508. With different firmwares, the board can function as a Bluetooth keyboard and mouse combo or a USB keyboard and mouse combo. The footprint will be TQFP with 0.5mm pitch, which is much easier to solder compared to QFN like the F5502 used in v0.6. The crystal used for USB functions has been replaced with a cheap resonator.

The rows and columns of the keyboard adapter will be connected to different pins on the MSP430, hoping to use its interrupts to save power when user is not typing.

There will be two ways to program the MSP430 as well as the Bluetooth on-board such as the HM-10 using a custom firmware. Debuggers can be connected to the 2.54mm headers or using a TagConnect cable.

HID firmware on HC-06 Bluetooth modules

371412603_147

TL;DR – HC-05/06 shares the same MCU used in the RN-42HID and RN-41HID. You can dump the firmware from these HID modules and transfer it onto the HC-05/06 modules. Doing so may infringe Roving Network’s intellectual property so it’s best if you don’t distribute their firmware. I post this because I found it interesting.

For educational purposes, I’ve been playing with these HC-05, HC-06 Bluetooth modules. They are cheap, widely available and their firmware can be changed. But the best thing about these modules is the microcontroller BC417 that is used to handle all their logic, the CSR Bluecore4-Ext, which shall be referred to from now as BC4-Ext.

CSR BC4 is available in different flavours, so far I’ve heard of BC4-Ext and BC4-ROM. The ‘Ext’ uses an external ROM to store some data, what, I can’t remember. These guys are the core of many Bluetooth modules, including the ones from Bluegiga and Roving Networks.

I have been learning to program these modules to handle UART communication to send HID key codes but it was difficult. The resources on this is quite limited and since Bluetooth 2.0 was so 2004, CSR Support website wasn’t of much help.

I wrote a custom firmware for the HM-10 CC2540/1 but it requires Bluetooth 4.0. For a keyboard and mouse, what good would Bluetooth 4.0 do. Bluetooth 2.0 is much more suitable as it is compatible with almost all Bluetooth devices that has been around for the last 10 years. In slight frustration, I gave in and bought a BlueSmirf RN-42-HID from Sparkfun. After reading the datasheet, however, it turns out they also use CSR BC4-Ext! This is great news.

The BlueSmirf arrived yesterday. After searching for the pinout of the RN-42, I soldered some jumper cables to its SPI pins and used a USB SPI programmer that is CSR-compatible and dump the firmware with BlueFlash. After flashing this firmware onto a HC-06 module, voilà, I now have an exact copy of a RN-42-HID in firmware.

There is still the issue of conflicting Bluetooth addresses, but may that be resolved by changing the PSR settings. Byron’s blogpost gives some steps on how this can be done. And of course, the firmware of the RN-42-HID will not be shared.