The BlueButton – Assembling & Testing First Prototype

The PCBs eventually arrived, however, this time it was somewhat disappointing: instead of usual two weeks the manufacturing process along with the shipment took almost four weeks. The quality seems to be fine and no ‘gotchas’ have been found so far so hopefully soldering will go smoothly.

This is how the PCBs look like:

BlueButton PCBs Manufactured

BlueButton PCBs Manufactured

The amount of components in this project is really small, it takes about 30 min… 1 hour to solder all of them. The only thing that needs to be kept in mind is that BLE module should be loaded before the battery holder and the P3 (CC_Debugger) connector. This would simplify the assembling process. The fully assembled board is shown below (top side of the PCBa):

BlueButton PCBA Top Side

BlueButton PCBA Top Side

… and bottom side:

BlueButton PCBA Bottom Side

BlueButton PCBA Bottom Side

Before the board can be programmed, we need to implement an application (also known as BGscript). As a base hid-over-gatt-keyboard application example is used as it in essence does everything that our BlueButton needs to do: it works as a HID keyboard over Bluetooth so no additional drivers on a host computer would needed. However, there some changes and enhancements that will be done to the original code. First change is in hardware.xml to pull port 0 pins up and port 1 – low. We also enable sleep mode “3” which is the most power preserving mode, however, it can’t be used in current application without additional changes which will be introduced later:

<?xml version="1.0" encoding="UTF-8" ?>
<hardware>
    <sleeposc enable="true" ppm="30" />
    <usb enable="false" />
    <txpower power="15" bias="5" />
    <script enable="true" />
    <slow_clock enable="true" />
    <!--pmux regulator_pin="7" /-->
    <port index="0" tristatemask="0" pull="up" />
    <port index="1" tristatemask="0" pull="down" />
    <sleep enable="true" max_mode="3" />
</hardware>

Second change is in the script. In system_boot we configure ports to enable the LED and interrupts from 5 buttons:

event system_boot(major, minor, patch, build, ll_version, protocol, hw)
    # configure P1.0 as output
    call hardware_io_port_config_direction(1, $1)

    # Pull low P1.0 pin. Parameters: I/O port to write to 0/1/2,
    #                               bitmask of pins to modify,
    #                               bitmask of pin values to set
    call hardware_io_port_write(1, $1, 0)

    # start advertising in connectable mode
    call gap_set_mode(gap_general_discoverable, gap_undirected_connectable)
	
    # remove all bonds (optional! normally this shouldn't be run on every boot)
    #call sm_delete_bonding($ff)
    
    # enable bondable mode for systems which want to use it
    call sm_set_bondable_mode(1)
    
    # enable interrupt on P0_0, P0_1, P0_2, P0_3, P0_4 rising edge ('A', 'B', 'C', 'D' and 'E' keys)
    # (parameters are port=0, bitmask=0b00001111, edge=rising)
    call hardware_io_port_config_irq(0, $1f, 1)

    # use default report mode for keyboard
    hid_attribute = hid_keyboard_in
end

Then when handling events from 5 buttons there are two additions: suppressing bouncing effect by disabling interrupts the any button for a specific time and activating LED to indicate button press:

# catch button press for P0_0, P0_1, P0_2, P0_3, P0_4 (active HIGH configuration, hardware.xml pulls it high)
event hardware_io_port_status(delta, port, irq, state)
    if port = 0 then
        # build HID report:
        # 0:0x02 = left shift (should be capital A or Z unless caps lock is on)
        # 1:0x00 = RESERVED
        # 2:0x?? = key down (will be set to either A or Z code below)
        # 3:0x00 = empty key slot
        # 4:0x00 = empty key slot
        # 5:0x00 = empty key slot
        # 6:0x00 = empty key slot
        # 7:0x00 = empty key slot
        report(0:8) = "\x02\x00\x00\x00\x00\x00\x00\x00"
        if (irq & $01) = $01 then
            # P0_0 is HIGH and the source of this interrupt, so use "A" code
            report(2:1) = $04   # "A" key code, 4
        end if
        if (irq & $02) = $02 then
            # P0_1 is HIGH and the source of this interrupt, so use "B" code
            report(2:1) = $05   # "B" key code, 5
        end if
        if (irq & $04) = $04 then
            # P0_2 is HIGH and the source of this interrupt, so use "C" code
            report(2:1) = $06   # "C" key code, 6
        end if
        if (irq & $08) = $08 then
            # P0_3 is HIGH and the source of this interrupt, so use "D" code
            report(2:1) = $07   # "D" key code, 7
        end if
        if (irq & $10) = $10 then
            # P0_4 is HIGH and the source of this interrupt, so use "E" code
            report(2:1) = $08   # "D" key code, 7
        end if
        
        # write HID report
        call attributes_write(hid_attribute, 0, 8, report(0:8))

        # build and write HID report for "release" action:
        # 0:0x00 = no modifiers (i.e. release previous left shift)
        # 1:0x00 = RESERVED
        # 2:0x00 = empty key slot (i.e. release previous 'A')
        # 3:0x00 = empty key slot
        # 4:0x00 = empty key slot
        # 5:0x00 = empty key slot
        # 6:0x00 = empty key slot
        # 7:0x00 = empty key slot
        report(0:8) = "\x00\x00\x00\x00\x00\x00\x00\x00"
        call attributes_write(hid_attribute, 0, 8, report(0:8))
        
        # Pull high P1.0 pin (switch LED on for 200 msec)
        call hardware_io_port_write(1, $1, 1)
    
        # Disable interrupts from the buttons
        call hardware_io_port_config_irq(0, $0, 1)
        
        #Set timer to generate single shot event in 100msec
        call hardware_set_soft_timer(3276, 1, 1)

        #Set timer to supress bouncing effect - no interrupts for next 500msec        
        call hardware_set_soft_timer(16380, 2, 1)
    end if
end

And finally, there is an extra function that handles events from two timers: when the LED is to be switched off and when interrupts from the buttons are to be enabled again:

event hardware_soft_timer(handle)
    if handle = 1 then
        # Pull low P1.0 pin (switch LED on for 200 msec)
        call hardware_io_port_write(1, $1, 0)
    end if

   if handle = 2 then
        # re-enable interrupts from the buttons again
        call hardware_io_port_config_irq(0, $1f, 1)
   end if
end

As a next step, the BLE112 module has to been programmed with the compiled script. In order to do this, a CC-Debugger is needed. It must be connected to the target board via convertor board 2.54 mm - 1.27 mm connector which comes with the debugger. The target board must be powered for the programming operation, in other words, a coin battery has to be installed. When CC-Debugger is plugged in to a PC via USB cable and when CC-Debugger and the target board are connected with a 10 pos. flat cable the LED on CC-Debugger should go green after pressing RESET button. The script is uploaded then to the target board by Bluegiga BLE upload tool.

BlueButton PCBA bing programmed by CC-Debugger

BlueButton PCBA being programmed by CC-Debugger

When programming is complete, CC-Debugger is unplugged and the board is then secured in a 3D printed enclosure by four self-tapping screws as shown on the picture below:

BlueButton Enclosure Exploded

BlueButton Enclosure Exploded

The fully assembled first prototype looks like this:

BlueButton Enclosure Assembled

BlueButton Enclosure Assembled

Downloads:

1. BlueButton Firwmare Rev1.0

The relevant video is given below: