Apple (or other) Installments and Banktivity (or Quicken, possibly)

I’m a long-time user of IGG Software’s Banktivity personal finance application. I switched from the incumbent, Quicken, ages ago, when I finally moved to Macs from PCs, back in the days of the PowerPC Mac and System 9. I was a long-time user of Quicken, going back to Quicken 4, through Quicken 95 etc etc. It made sense to use Quicken for the Mac but at that time, Intuit’s Mac support was pretty much crap and I looked for an alternative and came across Banktivity. Banktivity has worked well for many years now and does everything I need.

With that said, I’ve come across one situation that’s just plain weird enough to not have an easy solution, and that is the use of an Apple Card to get 0% financing for certain Apple products. Searching the web for “Banktivity Apple installments” or “Quicken Apple installments” doesn’t give any useful solutions, only some questions on the Quicken forum. And those questions don’t give good answers, either. Hopefully the web crawlers will find this blog post so others can find it and maybe it will be useful.

(Don’t get me started on Apple/Goldman Sachs’ refusal to allow simple downloads of transactions when using a computer. Sorry, Apple/GS, adults do not do their financial management on a smartphone, and this is why my use of the Apple Card is limited to mostly Apple Store hardware purchases.)

Consider: You want to buy a $999 MacBook Air. If you were to purchase this product outright at the local store, you will pay (in Tucson, Arizona) $1,086.91, including the sales tax. You will get a receipt for $1,086.91 and you can enter it as a purchase in your finance application with a category of “Computer Hardware.” This makes it easy to categorize your purchases (one reason to use a personal finance program), and also if your purchase was a business expense that can be written off, it’s one entry in the ledger and easily found when doing taxes.

The Apple installment plan is nice: you simply spread out the payments over a year (or two for the phones) and they don’t charge interest. A question you can ask: “Is this a loan?” The answer matters if you want to handle this in your personal finance program.

If you answer “Yes,” then you might want to do the obvious, which is to set up a loan account. But it’s not as simple as that. For starters, you would think that a big purchase like a computer would be considered an asset you can track, but the only loans in Banktivity that can be against an asset is a mortgage.

Next, usually when you think of a “loan” there is some banking institution that gives you money and sets up a payment schedule, and every month you make a payment from your cash bank accounts to the loan account.

Apple installments do have a payment schedule, but there is no loan account as such. Rather, they just charge your credit card at the end of the month for the installment amount, and then you have to pay the credit card from one of your cash accounts. But that’s OK. You could set up an “Other Loan” account in Banktivity, one that is not linked to a financial institution, and enter the loan amount/starting balance as the purchase price of the laptop. Set the interest rate and the payment, and tell it that the payment account is the Apple Card. It will create the loan account and a scheduled transaction for the number of payments, and it will put an entry in the loan’s ledger of a starting balance equal to the purchase price of the computer. Change the category of the starting balance from “Starting Balance” to “Computer:Hardware” or something that makes sense.

Great, right? There’s one problem, which is that Apple will charge your card for the amount of sales tax ($86.91, in this case) and they’ll set up your installment plan for the price of the computer exclusive of that sales tax. The loan’s initial balance is $999, not $1,085,91. How the heck do you create an entry for the full purchase price of the computer, including the tax? Remember you want to do a report at tax time that shows the full price of the computer, and not have to deal with two ledger entries in two accounts for that price.

Here is what works for me.

First, create a new account that is an “Asset or liability not held at any financial institution.” This is because your “loan” is a fiction.

Create an account

Make it a Liability Account.

Account type and name

Enter the full purchase price as the Balance, and enter the date of purchase as the “as of date” amount.

Account initial balance

And Banktivity has now created the account and your initial balance is the purchase price.

Liability account after creation

Change the Payee to Apple Store (you bought the laptop from the Apple Store), give it a proper category (and tag if you like).

Update the ledger to show the purchase

Remember that Apple immediately charged your Card for the sales tax, so create a new transaction that is a charge to your Apple Card:

Sales tax is charged to Apple Card immediately

Finally, create a Scheduled Transaction that will charge your Apple Card each month for the amount of the installment.

Make a scheduled transaction for the “loan” payment

And set it for 12 payments.

Make it 12 payments

And that’s it! Every month for the next 12 you will have to enter the scheduled transaction you created for the “loan” and that will charge your Card for the amount of the “loan.” After 12 months the schedule ends.

Hope this helps.

More on Kicad libraries

Previously I wrote about how I handle Kicad libraries. That all is still quite valid for the current version of Kicad (5.1.6).

I thought that I should add both the Numbers spreadsheet that is my “parts database,” as well as the Python script I use to create an orderable BOM from the BOM exported from a Kicad schematic and that parts database.

The Python script is here.

The Numbers spreadsheet parts list is here. Export the spreadsheet as a CSV file for use with the script.

A USB MIDI Class Device implemented on the SiLabs EFM8UB2 Microcontroller

Introduction

An upcoming project requires a MIDI connection over USB. The product is simple: it’s a MIDI-controlled “thing” with some front-panel buttons and knobs and LED indicators as the user interface. The buttons and knobs control device parameters with status reflected by the LEDs. If a host computer is connected to the device over USB, then that computer can control it with a “virtual” front panel, and also changes made on the real panel are sent to the computer so the device and the computer can remain synchronized.

USB has supported MIDI devices, as a part of the USB Audio Device Class, since 1999, and the three major operating systems have built-in drivers for them. MIDI itself has been around even longer. Both specifications are mature, well-understood and well-supported.

An embedded microcontroller can be used to manage the USB interface and the other digital stuff. At first glance, implementing USB MIDI on a micro seems straightforward. After all, there is USB MIDI support for Arduino, and there’s a project for the STMF32 parts, and of course there’s the LUFA library which targets various Atmel parts.

For various reasons, I prefer Silicon Labs micros. While none of SiLabs’ USB micros (both 8-bit 8051 and 32-bit ARM) support High Speed, that is fine, as the USB MIDI class was specified for Full Speed. SiLabs provides an Eclipse-based IDE called Simplicity Studio which works as well as can be expected. The Keil C51 compiler tools are used for building C8051 and EFM8 projects (and the gcc compiler is used for the EFM32 ARMs) and C2-based programming and debug is built in. Finally, SiLabs provides a decent USB stack to handle most of the details of the USB interface.

The SiLabs USB stack doesn’t have support for the MIDI device class. And they don’t have an example of how to use the stack with devices that use Bulk transfers. OK, no problem, it’s time to write some code!

The USB MIDI device described here has two functions. One, it implements a USB-to-serial-MIDI dongle like the various M-Audio things, so it will use a UART to drive and receive messages over the standard MIDI DIN connector interface. Two, it allows the host to control “features” of a device, in this case an RGB LED, as well as allowing the device to send user-interface control changes (buttons, knobs) back to the host.

It will run on the SiLabs EFM8UB2 STK. Since MIDI requires an optoisolated receiver, a simple board must be built to support that. A schematic is shown later.

I will assume that the reader is familiar with the MIDI Specification, both at the physical layer and the protocol layer, so I won’t rehash any of that. I will point out where USB-MIDI and the standard MIDI overlap and where the former extends the latter.

USB-MIDI Device Class Basics

Note to the reader: it is helpful to have the USB MIDI and the USB Audio Class specs available. The USB MIDI class is a subclass of sorts under the Audio Class umbrella. The device descriptor requires an Audio Control Interface. For the actual MIDI data, the device must include one or more MIDI Streaming interfaces instead of an Audio Streaming interface. (The device can include one or more Audio Streaming interfaces if desired and if the converter hardware is available.)

The topology of a USB MIDI device function is described with a few different blocks and the connections between them. It must have a USB-MIDI Converter, and one or more Jacks are used to describe the source or sink of a MIDI data stream within the device. Elements are used to describe engines that convert MIDI data to audio or the converse. For purposes of this example, we do not use Elements. (This might change.) Also, the USB MIDI device class supports “Transfer Endpoints,” which are used to exchange data between the host and any defined Elements, and again for this example we do not use them.

There are two types of Jacks: Embedded and External. The easiest way to think of these two types is that Embedded Jacks describe connections where the MIDI data stay within the device, and External Jacks describe physical connections such as the standard DIN jack driven by a 31.25 kbps asynchronous serial transmitter. I believe that the proper use of Elements would be to have them be the source and sink for data going over Embedded Jacks, and a future revision of this code might take advantage of that. For now, I use External Jacks to describe how buttons are read and LEDs are set.

USB-MIDI “Cables”

Full-Speed MIDI has a wire rate of 12 Mbps, which is significantly faster than the MIDI UART’s rate of 31.25 kbps. This allows for one of the USB MIDI Class’s more interesting features, which is multiplexing multiple MIDI streams. This is done using virtual “ports” which are called “cables” in the USB MIDI spec. Up to sixteen “cables” can be muxed onto one USB Endpoint. It is as if each device had 16 MIDI Out ports and 16 MIDI In ports, of course without the nest of wires. And with the standard sixteen channels per virtual “cable,” a lot of MIDI messages can be sent and received on one USB cable.

MIDI Device Class Descriptors

The internet has very few examples of MIDI Device class descriptors. The aforementioned LUFA code has a generic descriptor, but it’s not clear what’s going on with it. I have a couple of USB-MIDI devices and a bus analyzer, so I was able to dump the descriptors for them to see what mine might look like. And between those dumps and the USB-MIDI spec, I came up with descriptors which work with the device design I described above. I apologize for including the Silicon Labs macros which are used to determine memory space. The descriptors are in a file conveniently called descriptors.c in the source code.

First we have the mandatory device descriptor:

SI_SEGMENT_VARIABLE(deviceDesc[],
	const USB_DeviceDescriptor_TypeDef,
	SI_SEG_CODE) =
{
	USB_DEVICE_DESCSIZE,            // bLength
	USB_DEVICE_DESCRIPTOR,		// bDescriptorType
	htole16(0x0200),		// bcdUSB
	0,				// bDeviceClass
	0,				// bDeviceSubClass
	0,				// bDeviceProtocol
	64,				// bMaxPacketSize
	USB_VENDOR_ID,			// idVendor
	USB_PRODUCT_ID,			// idProduct
	htole16(0x0100),		// bcdDevice
	1,				// iManufacturer
	2,				// iProduct
	3,				// iSerialNumber
	1,				// bNumConfigurations
};

The various constants must be defined somewhere, and in this case the first two are in the library source efm8_usb.h, as they are standardized and do not vary from design to design. The last two are design-dependent, and are in descriptors.h which is intended to be changed by the user.

The entries for bDeviceClass and bDeviceSubclass are zero, which indicates that the device is defined at the Interface level (which is pretty standard).

Next is the Configuration Descriptor. This is what tells the host about the device, and it tells how many Interfaces are included. Each Interface has both Standard and Class-specific descriptors.

In this design, there are two interfaces. One is the mandatory (for an Audio Class device) Audio Control interface, which tells the host that it’s an Audio Class device. This interface has two descriptors, the mandatory Standard Interface Descriptor and a Class-Specific Interface Descriptor. The second interface is the MIDI Streaming interface, which describes how the device handles data. This second interface has a mandatory Standard Interface Descriptor, and a Class-Specific Interface descriptor. A large part of the CSIF descriptor are the eight Jack descriptors, which tells the host about the device’s MIDI data routing. Finally, because the MIDI streaming interface presents MIDI In and MIDI Out data paths, there are two Endpoints for them. Each Endpoint has a Standard Endpoint descriptor and a Class-Specific Endpoint Descriptor.

/*
 * This is the Configuration Descriptor.
 */
SI_SEGMENT_VARIABLE(configDesc[],
    const USB_ConfigDesc_t,
    SI_SEG_CODE) =
{
// Configuration Descriptor header
	USB_CONFIG_DESCSIZE,		// bLength
	USB_CONFIG_DESCRIPTOR,		// bDescriptorType
	htole16(0x0085),		// wTotalLength, 133 bytes
	2,				// bNumInterfaces
	1,				// bConfigurationValue
	4,				// iConfiguration
	CONFIG_DESC_BM_RESERVED_D7,     // bmAttributes
	CONFIG_DESC_MAXPOWER_mA(100),   // bMaxPower
// Standard Interface Descriptor for Audio Control Interface
	USB_INTERFACE_DESCSIZE,		// bLength
	USB_INTERFACE_DESCRIPTOR,	// bDescriptorType
	0,				// bInterfaceNumber
	0,				// bAlternateSetting
	0,				// bNumEndpoints, this
                                        // uses the control endpoint
	USB_CLASS_AUDIO,		// bInterfaceClass
	USB_AUDIO_AUDIOCONTROL,		// bInterfaceSubClass
	0,				// bInterfaceProtocol
	5,				// iInterface
// Class-Specific Audio Control Interface Descriptor
	sizeof(USB_MIDI_CS_AC_IF_Descriptor_t),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,	// bDescriptorType
	MIDI_CS_IF_HEADER,		// bDescriptorSubtype
	htole16(0x0100),		// bcdADC
	htole16(0x0009),		// wTotalLength
	1,				// bInCollection
	1, 				// baInterfaceNr
// Standard Interface Descriptor for MIDI Streaming Interface
	USB_INTERFACE_DESCSIZE,		// bLength
	USB_INTERFACE_DESCRIPTOR,	// bDescriptorType
	1,				// bInterfaceNumber
	0,				// bAlternateSetting
	2,				// bNumEndpoints
	USB_CLASS_AUDIO,		// bInterfaceClass
	USB_AUDIO_MIDISTREAMING,	// bInterfaceSubClass
	0,				// bInterfaceProtocol
	6,				// iInterface
// Class-Specific Interface Descriptor for MIDI Streaming Interface
	sizeof(USB_MIDI_CS_MS_IF_Descriptor_t),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,	// bDescriptorType
	MIDI_CS_IF_HEADER,		// bDescriptorSubtype
	htole16(0x0100),		// BcdADC
	htole16(0x0061),		// wTotalLength
// Class-Specific Interface Descriptor for MIDI Jack 1.
// This jack is the sink for data from the USB host and intended for
// the "onboard" "port," which controls the RGB LED.
// This should appear as Outport MIDI Port 1 to the host computer.
// It connects to the USB OUT Endpoint 1.
	sizeof(USB_MIDI_In_Jack_Descriptor_t),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,	// bDescriptorType
	MIDI_CS_IF_IN_JACK,		// bDescriptorSubtype
	MIDI_JACKTYPE_Embedded,		// bJackType
	JACK1_EMBIN,		        // bJackID 
        0, // Jack index of a string descriptor describing this jack
// Class-Specific Interface Descriptor for MIDI Jack 2.
// This jack is the source of MIDI packets intended to be used by the
// "onboard" "port" which controls the RGB LED. It connects to one
// source, which is Jack 1.
// It is an "External" type because it connects to stuff outside of
// the USB MIDI function. Can this be embedded?
	USB_MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,		// bDescriptorType
	MIDI_CS_IF_OUT_JACK,			// bDescriptorSubtype
	MIDI_JACKTYPE_External,			// bJackType
	JACK2_EXTOUT,				// bJackID
	1,					// bNrInputPins
	JACK1_EMBIN,				// baSourceID
        1,					// baSourcePin
	0,					// iJack
// Class-Specific Interface Descriptor for MIDI Jack 3.
// This jack is an input to the USB MIDI function, and it gets its 
// data from the changes to the buttons and joystick.
	sizeof(USB_MIDI_In_Jack_Descriptor_t),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,		// bDescriptorType
	MIDI_CS_IF_IN_JACK,			// bDescriptorSubtype
	MIDI_JACKTYPE_External,			// bJackType
	JACK3_EXTIN,				// bJackID 
	0,					// iJack
// Class-Specific Interface Descriptor for MIDI Jack 4.
// This jack is an output from the USB MIDI function, and it feeds the
// USB In Endpoint. It gets its data from Jack 3, that is, the buttons
// and joystick. 
// This should appear as MIDI INPUT Port 1 to the host computer.
	USB_MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,		// bDescriptorType
	MIDI_CS_IF_OUT_JACK,			// bDescriptorSubtype
	MIDI_JACKTYPE_Embedded,			// bJackType
	JACK4_EMBOUT,				// bJackID
	1,					// bNrInputPins
	JACK3_EXTIN,				// baSourceID
	1,					// baSourcePin
	0,					// iJack
// Class-Specific Interface Descriptor for MIDI Jack 5.
// This is the source of the MIDI data packets intended for the serial
// MIDI OUT port. It should appear as MIDI OUTPUT Port 2 to the host.
// It connects to the USB OUT 1 Endpoint.
	sizeof(USB_MIDI_In_Jack_Descriptor_t),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,		// bDescriptorType
	MIDI_CS_IF_IN_JACK,			// bDescriptorSubtype
	MIDI_JACKTYPE_Embedded,			// bJackType
	JACK5_EMBIN,				// bJackID
	0,					// iJack
// Class-Specific Interface Descriptor for MIDI Jack 6
// This is the sink for the MIDI data packets intended for the serial
// MIDI OUT port. It gets its data from Jack 5.
	USB_MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,		// bDescriptorType
	MIDI_CS_IF_OUT_JACK,			// bDescriptorSubtype
	MIDI_JACKTYPE_External,			// bJackType
	JACK6_EXTOUT,				// bJackID
	1,					// bNrInputPins
	JACK5_EMBIN,				// baSourceID
	1,					// baSourcePin
	0, 					// iJack
// Class-Specific Interface Descriptor for MIDI Jack 7
// This is the sink for data coming from the serial MIDI IN port, to
// go back to the host computer.
	sizeof(USB_MIDI_In_Jack_Descriptor_t),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,		// bDescriptorType
	MIDI_CS_IF_IN_JACK,			// bDescriptorSubtype
	MIDI_JACKTYPE_External,			// bJackType
	JACK7_EXTIN,				// bJackID 
	0,					// iJack 
// Class-Specific Interface Descriptor for MIDI Jack 8
// This is the source of the data for the USB IN Endpoint. It gets its
// data from Jack 7, which is fed by the DIN MIDI IN Port.
// This connects to USB IN Endpoint 1. 
	USB_MIDI_OUT_JACK_DESCRIPTOR_SIZE(1),	// bLength
	USB_CS_INTERFACE_DESCRIPTOR,		// bDescriptorType
	MIDI_CS_IF_OUT_JACK,			// bDescriptorSubtype
	MIDI_JACKTYPE_Embedded,			// bJackType
	JACK8_EMBOUT,				// bJackID
	1,					// bNrInputPins
	JACK7_EXTIN,				// baSourceID
	1,					// baSourcePin
	0,					// iJack
// Standard Endpoint Descriptor for Bulk In Endpoint 1
	USB_ENDPOINT_DESCSIZE,			// bLength
	USB_ENDPOINT_DESCRIPTOR,		// bDescriptorType
	0x81,					// bEndpointAddress
	USB_EPTYPE_BULK,			// bmAttributes
	htole16(SLAB_USB_EP1IN_MAX_PACKET_SIZE),// wMaxPacketSize
	0,					// bInterval
// Class-specific Endpoint Descriptor for Bulk In Endpoint 1
	USB_MIDI_CS_STREAMING_BULK_ENDPOINT_SIZE(2),	// bLength
	USB_CS_ENDPOINT_DESCRIPTOR,		// bDescriptorType
	USB_MIDI_CS_EP_MS_GENERAL,		// bDescriptorSubtype
	2,					// bNumEmbMIDIJack
	JACK4_EMBOUT, JACK8_EMBOUT, 		// baAssocJackID
// Standard Endpoint Descriptor for Bulk Out Endpoint 1
	USB_ENDPOINT_DESCSIZE,		// bLength
	USB_ENDPOINT_DESCRIPTOR,	// bDescriptorType
	0x01,				// bEndpointAddress
	USB_EPTYPE_BULK,		// bmAttributes
	htole16(SLAB_USB_EP1OUT_MAX_PACKET_SIZE),// wMaxPacketSize
	0,				// bInterval
// Class-specific Endpoint Descriptor for Bulk Out Endpoint 1
	USB_MIDI_CS_STREAMING_BULK_ENDPOINT_SIZE(2),	// bLength
	USB_CS_ENDPOINT_DESCRIPTOR, 	// bDescriptorType
	USB_MIDI_CS_EP_MS_GENERAL,	// bDescriptorSubtype
	2,				// bNumEmbMIDIJack
	JACK1_EMBIN, JACK5_EMBIN	// baAssocJackID
};

USB-MIDI “Jacks”

The relationship between the Jacks, and between the Jacks and the Endpoints is likely the most confusing aspect of this. Remember that the Jacks describe the inputs to and the outputs from the USB-MIDI function. And what might seem even more confusing is that more than one Jack can be associated with a particular part of the function. So let’s look at this in more detail.

Recall that this example design has four MIDI ports. Two are the standard serial ports (wired MIDI In and Out on DIN connectors) and the other two are a virtual “Out” port that lets the host control stuff (the RGB LED in this example design) and a virtual “In” port that sends button-press data back to the host. This means there are four data “paths” and we need eight Jacks — four In, four Out — to describe this routing, and the descriptors above show them. Pay attention to the Class-Specific Endpoint Descriptors, as they specify how data are routed to or from the Endpoint from or to the Jacks, and note that the endpoints each feed two Jacks.

  • Data path from host computer to control RGB LED:

OUT Endpoint 1 -> Jack 1 -> Jack 2 -> LED

  • Data path from joystick and button handler to host computer:

Button handler -> Jack 3 -> Jack 4 -> IN Endpoint 1

  • Data path from host computer to DIN MIDI OUT port:

OUT Endpoint 1 -> Jack 5 -> Jack 6 -> serial transmitter/MIDI OUT DIN port

  • Data path from DIN MIDI IN port to host computer:

Serial receiver/MIDI IN DIN port -> Jack 7 -> Jack 8 -> IN Endpoint 1

But … what about “Cables?”

Indeed, what about cables? The descriptors say nothing about them at all! It seems obvious that with one OUT Endpoint, we connect to the MIDI OUT DIN connector and the LED on different cables, and also the buttons/joystick connect to the one IN Endpoint on a different cable from the MIDI In DIN connector. Thus the USB OUT Endpoint connects to two cables and the USB IN Endpoint connects to two cables. (That’s why the Jacks are specified in the Class-Specific Endpoint Descriptors.)

All the descriptors do is to tell the host computer about the topology of the MIDI “network,” if you will, associated with the device. They don’t indicate how that topology is actually implemented. That’s up to the firmware. But how does the firmware know how to actually do all of this routing that the device told the host it can do? Well, first, we must introduce the USB-MIDI Event Packet (MEP).

The USB-MIDI Event Packet

Readers familiar with standard serial MIDI know that MIDI Messages are sent in packets of one, two or three bytes for non-SysEx messages, and SysEx messages can have any number of bytes between the SOX and EOX status bytes. USB-MIDI standardizes on a four-byte MIDI Event Packet, shown here:

MIDI Event Packet

Byte 0 is the packet header. Its upper nybble is the four-bit Cable Number. This tells the device which cable the packet came from (in case of USB IN Endpoints) or which cable is the destination for the packet (for USB OUT Endpoints). The lower nybble of the header is the Code Index Number, which indicates how the remaining three bytes of the packet should be interpreted. For most of the packets, the three payload bytes are a standard MIDI message, so the CIN can appear to be redundant. But this is also how multibyte SysEx messages can be broken up into three-byte chunks to fit into the USB-MIDI Event Packet.

MIDI Event Packets on the USB and this example design

For USB OUT Endpoint MIDI transactions: the host will fill its USB OUT packets with one or more MEPs, up to the Endpoint’s maximum packet size, based on the MIDI traffic generated by applications. The USB packet ends up in the device micro’s Endpoint buffers in a device-specific manner. At some point, the micro’s USB interrupt is asserted and parsed and now we have our Event Packets sitting in a buffer, waiting to be handled. The handler itself is in the main() function in EFM8-USB-MIDI_main.c.

The micro firmware should pop an MEP from the buffer and inspect its header. The Cable Number and the Code Index Number tell the micro how to handle the packet. In the case of our simple example, Cable Number 0 is the “virtual” device where the USB OUT controls the RGB LED. Cable Number 1 goes to the serial MIDI Out port. (My unproven assumption is that since the Class-Specific Endpoint Descriptor tells the host how many “Ports” or cables the device has, the host won’t do something silly like send a packet to a non-existent Cable Number.)

Packets intended for the hardware serial port have the CIN parsed and a standard MIDI message packet is built from the MEP. That packet is then sent to the serial transmitter’s holding FIFO.

For packets intended for the “virtual” port, which controls the RGB LED, the first payload byte is inspected. We use MIDI Control Change messages to set the brightnesses of the three colors. The message indicates which control (in byte 2 of the Event Packet) and also the control’s value (in byte 3). If the control matches one of the four we expect (I chose GP Control 5, 6, 7 and 8), the value is used to set the LED color and intensity. Other controls are simply ignored.

For USB In Endpoint MIDI Transactions: This is where the micro takes either events on the buttons and joystick, or messages from the serial MIDI IN connection, and builds MIDI Event Packets and sends them back to the host.

For the former, periodically the micro polls the state of the joystick and buttons and builds a report with the state of those controls. Then a parser in main() tests the state of each control, and if toggled, a MEP is built for a Control Change message with the appropriate state, and that packet is written to the micro’s USB device endpoint FIFO to be sent off to the host.

For the latter, MIDI messages coming from the serial MIDI In must be parsed and one or more proper MEPs built. The parsing is done by a state machine in the file midi_uart.c in the function MIDIUART_readMessage(). This parsing is rather more complex than one might expect, as a message might not be fully received when that function is called. Also it needs to handle MIDI running status and the varying sizes of SysEx messages. In any case, the function builds MEPs on the fly and when one is completed, the function returns the MEP in a point argument and returns true, and the main() function will then just write the entire MEP to the Endpoint buffer.

The EFM8UB2 and the Silicon Labs EFM8 USB stack

There is some discussion of how to use this stack over at the SiLabs 8-bit MCU forum, and I had some back and forth with SiLabs tech support to get to the bottom of how the part works. It turns out that there are some important details left out of the part documentation.

The code uses the efm8_usb library. The basic idea, after getting the descriptors correct and having it actually enumerate on the USB, is that you access the stack through two API functions, USBD_Write() and USBD_Read(), and you get access to read data (from a USB OUT transaction) using the transfer-complete callback USBD_XferCompleteCb().

USBD_Write()

The USBD_Write(), to write data to the host for a USB IN transaction, is relatively straightforward. You just pass to that function a pointer to a buffer containing the data to send, the size of that buffer and the Endpoint number, and off it goes. You can also indicate whether you want a callback after the transaction is complete, but for this case none is needed. I did find it to be necessary to ensure that the endpoint was not busy before calling USBD_Write(). Examples of this are in my main() function in EFM8-USB-MIDI_main.c.

USBD_Read()

The USBD_Read() is not as simple, and the lack of documentation about how it is supposed to work doesn’t help. (This is why my question on the forum was “when are you supposed to call this function?”) Despite its name, this function doesn’t return a buffer full of data from the last USB OUT transaction. Rather, it hands a buffer over to the stack and then the stack indicates internally that it is ready to handle USB OUT transactions. It “primes the pump,” so to speak. But this still doesn’t answer my question, so let’s do that now.

First, enable the USBD_DeviceStateChangeCb() callback. This will get called after the device has successfully enumerated on the USB, and the stack sets the device state to “configured.” This means that the device is now on the bus and ready for action. The host may now start sending USB MIDI packets to the device. First, create a global variable that is the size (in bytes) of the OUT Endpoint’s maximum packet size. (Realize that the Endpoint packet is not the same as the MIDI Event Packet!)

SI_SEGMENT_VARIABLE(
    EndpointBuffer[SLAB_USB_EP1OUT_MAX_PACKET_SIZE], 
    uint8_t, 
    SI_SEG_IDATA);

I put this line in the source file callback.c, the same file which contains the callbacks described above. (The file is generated by Simplicity Studio’s configurator, but thankfully it is not overwritten by later configuration changes.) Since we use this global variable in other places, you must extern it wherever else you use it (or put it in a header with the extern decoration).

In this callback, then, we do the initial call to USBD_Read():

void USBD_DeviceStateChangeCb(USBD_State_TypeDef oldState,
                              USBD_State_TypeDef newState) {
	UNREFERENCED_ARGUMENT(oldState);
	if (newState == USBD_STATE_CONFIGURED) {
		USBD_Read(EP1OUT,
			&EndpointBuffer,
			SLAB_USB_EP1OUT_MAX_PACKET_SIZE,
			true);  // Call XferCompleteCb when buffer full.
	}
} // USBD_DeviceStateChangeCb()

And now the device is ready to handle the first USB transaction on Endpoint Out 1. Note that we have set the “use callback” argument to TRUE.

In the endpoint interrupt handler (part of the efm8_usb stack) the first thing that happens is that the number of bytes in the Endpoint FIFO is fetched. Then that number of bytes is popped from that FIFO and stored in our Endpoint buffer (passed in the call to USBD_Read()). At that point, we have one or more MIDI Event Packets sitting in our buffer, waiting to be handled, and this is when the transfer-complete callback is invoked.

uint16_t USBD_XferCompleteCb(uint8_t epAddr, USB_Status_TypeDef status,
		uint16_t xferred, uint16_t remaining) {

	USBMIDI_Message_t xdata mep;
	uint8_t *epb;

	UNREFERENCED_ARGUMENT(remaining);

	if ((epAddr == EP1OUT) && (status == USB_STATUS_OK))
	{
		epb = EndpointBuffer;
		while (xferred) {
			mep.header = *epb++;
			mep.byte1 = *epb++;
			mep.byte2 = *epb++;
			mep.byte3 = *epb++;
			USBMIDIFIFO_Push(&mep);
			xferred -= 4;
		}
	}

	// always return zero for bulk endpoints.
	return 0;
} // XferCompleteCb

In the callback we make sure we’re handling EP1OUT’s event. Then we build one or more MIDI Event Packets and push them onto a FIFO for later parsing. There’s a big assumption here, which is that the number of bytes transferred to our Endpoint buffer in the ISR is a multiple of the size of the MIDI Event Packet (four bytes). It might be a good idea to always check for that to be true, and then figure out how to handle it, lest we go off into the weeds with the buffer pointer.

Back in the main program loop, the call to USBMIDIFIFO_Pop (&usbmep) checks to see if the FIFO written by the callback actually has anything in it, and if so, one Event Packet at a time is popped and parsed.

So, really, when do we call USBD_Read()?

And the above still does not answer the question, “… so when do we call USBD_Read()?” I’m afraid that the answer is rather implementation-dependent and it also involves a detail of how the EFM8UB2’s USB serial-interface engine.

In most cases, a device is able to handle each USB OUT transaction’s input (to the micro) data in a timely manner, that is, before the next packet comes in. That is partially the case here, as MIDI Event Packets for the “virtual” Cable (which lights the RGB LED) is handled immediately and there’s no concern about not being ready for the next packet. So in that case, we can call USBD_Read() again immediately after we’ve parsed a packet.

But our example device has a complication: one of its functions is as a “USB to MIDI converter” dongle, so all MIDI Event Packets on the “real” Cable are just handed off to the UART that implements the serial transmitter for the DIN connector. And the rub is that the UART at 31.25 kbps is much much slower than Full Speed USB, and if you’re sending packets from a computer over USB, you can eventually overflow any FIFO you can put in front of your serial transmitter.

USB does offer the correct way for a device to throttle the bus in this sort of circumstance. Generally, in response to a transfer from the host, the device will send an ACKnowledge packet back. This lets the host know it can send more data. However, if the device is temporarily unable to deal with new data, it should respond by sending a No Acknowledge (NAK) packet back to the host. The host will see that, and at some point later it will retry sending the previous packet that the device was unable to handle. If the device NAKs again, the host will retry again, and keep doing so until the device finally accepts the packet.

I challenge you to read through the EFM8UB Reference Manual and tell me where it says how you are supposed to have the device NAK a transaction. Spoiler: you won’t find it. But SiLabs tech support was helpful in this, and there’s a simple and effective answer.

For each enabled Endpoint (IN or OUT) in the design, the EFM8UB2 has a FIFO. For USB OUT transactions, the deserialized data bytes are written to that FIFO. When the transactions are complete, the USB interface engine automatically sends the ACK response and then it interrupts the processor, which then figures out what to do.

But, for the OUT transactions, that interrupt is asserted only if a call to USBD_Read() was made. The interface continues to ACK each transaction. If no call, then the FIFO continues to fill as packets are received. And at some point, that FIFO is full. And when the FIFO is full, the USB interface will no longer ACK transactions, but rather it NAKs them.

Therefore, the USB interface was designed to do exactly what is required in the case when the device is not ready to deal with new data. It’s just not documented.

When the device is ready to deal with new data, all it needs to do is call USBD_Read() and then the USB interrupt will be immediately re-enabled, which means the ISR will get called right away and the oldest data in the FIFO will be transferred to the user buffer. And as the Endpoint FIFO empties, the host is re-trying the packet that was NAKed and eventually it will be ACKed and accepted. So no data packets are lost. (I should point out that this applies only to Bulk and Interrupt transactions, and not to Isochronous transactions, which are never NAKed and anyway cannot be retried.)

Back to our example, which is where we want to transmit received MIDI Event Packets out over the much slower serial port. In this case, those packets are re-formatted for the serial MIDI format and the packets are written to a FIFO that’s in front of the serial transmitter. If that FIFO gets full, obviously it cannot accept more packets. So after receiving an MEP and dealing with it (remember it might be for the internal “virtual” port), we see if there’s room for more in serial packet FIFO, and if so, then we’ll call USBD_Read() again. If there is no room in the FIFO, then we don’t, and let the serial transmitter pop bytes from it and eventually it has room again, and we can re-arm the endpoint and continue.

This example

The source code is available here (.zip). It was created using Simplicity Studio 4 and its Hardware Configurator, and as noted above it targets the EFM8UB2 STK, so as part of the design set-up it pulled in the various BSP features of interest (the joystick, the buttons, the RBG LED). I created directories called usb_audio, which has a couple of headers which define things, as well as the implementation of the USB-MIDI Event Packet FIFO. I also created a directory called midi, which also has useful defines. The most interesting stuff is in midi_uart.c. This is where you will find the code that implements the FIFOs in front of the micro’s UART1, and the MIDIUART_readMessage() function, which parses MIDI messages from the serial receiver and creates MIDI Event Packets.

Unzip and import into your Simplicity Studio 4 workspace in the usual way. It should build for the EFM8UB20F64G-x-QFP48 without incident, and it can be loaded onto the STK directly. In order to use the old-style serial MIDI interface, you need to build up a little board that connects to the pins for UART1. A reasonable schematic is here (taken directly from the MIDI spec). A 6N138 optoisolator works well.

MIDI interface hardware

Some final comments. First and foremost, this is meant to show valid USB-MIDI Class descriptors and implement a USB-to-MIDI converter like the M-Audio Uno. It also shows how incoming (via USB Out) messages can be parsed and used to control something on a board, and it shows how to build messages from button presses to report user-interface changes back to the host.

It is not a synthesizer/sound-generator module, although there’s no reason why one cannot expand on this to do so. MIDI Note-On and Note-Off messages are easily parsed and used to do what their names imply. (Perhaps one could use the micro’s PWM and play different-frequency notes based on the Note-On and Note-Off messages.)

Also, it is not intended to be the be-all/end-all explanation of how USB-MIDI is supposed to work.

Using “Atomic” Parts Libraries in Kicad

In a previous post, I discussed two approaches to Kicad library organization. Here, I will go into detail on how I’ve set up my libraries, which use the atomic parts paradigm. Remember: the goal here is to save time and effort. With atomic libraries, you research and vet all parts once, at the time they are put into the library, instead of doing it for each part after completing the layouts for each design.

The Master Parts List

Before we can put parts into a library, we have to know what parts we want to put into the library! Sure, that’s a tautology, but it’s also true. And it implies that we must have a scheme to keep track of parts.

So, what, exactly, is a “part” (or “component,” which we will use synonymously here)? Simple: it is anything that we want to use in a design. Generally, that means the usual electronic bits (resistors, transistors, op-amps, etc) as well as mechanical parts (standoffs, screws, even enclosures) and things that complete the design but don’t get soldered to a board (external power supplies, user manual). All of these things are kept in a Master Parts List, and everything gets a Company (or House) Part Number. This is all for the convenience of the whole organization: engineering needs to know what parts are allowed for use in designs, purchasing needs to know what to buy, assembly techs need to know what to put in kits, and so forth.

A master parts list can be maintained in a system as complicated as an enterprise-resource system, or in a simply MySQL database, or even as a spreadsheet. A minimal master parts list should contain the company part number (the key), a vendor name, that vendor’s part number, and a description. Nice to have, especially for keeping track of inventory, are entries for quantity on hand and estimated cost. My parts list also includes which library the part lives in, the footprint, and the footprint library associated with the part. My master parts list “database” is nothing more than an Apple Numbers spreadsheet.

A part numbering system

My “company part numbers” follow a simple scheme. It’s best explained with an example: A-1000-1 where:

  • A is a letter indicating a category (ICs, resistors, capacitors, transistors, mechanical parts, electromechanical parts, etc).
  • 1000 is a part number within the category, which distinguishes parts in the category and simply increments from the previous (1000 is the first part in the list, 1001 is the second, and so forth). For some categories, the part number indicates the part “family.” More on that below.
  • 0 is a numeral indicating part-number “variant.” A variant is where most of the parts sharing a part number are the same, but there is one (and only one) difference, such as package. For part “families,” this is used to indicate the value.

My categories include A for ICs, B for resistors, C for capacitors, D for transistors, E for diodes, F for electro-mechanical (switches, encoders, connectors) and so forth. My category G is for mechanical parts, such as screws, knobs, light pipes, enclosures.

Footprint libraries

My footprint libraries, all in the .pretty format, are broadly organized by category, and each library name is prefixed with asp_ to avoid collisions with other libraries. Most footprints have an associated 3D model, where I could find one. There is otherwise nothing non-standard about them.

Schematic symbol libraries

My schematic symbol libraries, all in the Kicad 4.0.x .sch format, are broadly organized by category, and each library name is prefixed with asp_ to avoid collisions with other libraries. None of the symbols have hidden power (or any other type) of pin. All parts have a useful description.

All symbols are for atomic components. This requires that they have a preselected footprint, and the footprints are in my libraries. A part called OPA551PA, which comes in the DIP-8 package, has its Footprint field filled with asp_ic:DIP-8. Also, each part must have a custom PN field, and it is in this field that I enter my company part number.

Yes, this means that each dual op-amp and each transistor and each whatever in the library will have essentially identical symbols. A reasonable response to concerns about this is, “So what!”

Naming the part symbols.

A simple requirement, yes? For most things, yes. ICs tend to be straightforward in this regard. Because the package is defined with atomic parts, the name of the part in the library should reflect it. Thus, my library has both LM317T (in the TO-220 package) and the LM317EMP (the SOT-223 package). These are, of course, the TI full part numbers, which encode the package type. The assumption is that the engineer has read enough of the data sheet to know the package codes so s/he can choose the desired device. The device description should indicate the package, so it’s obvious, and post-4.0.5 nightly builds include the footprint in the schematic symbol browser, so there shouldn’t be any complaints about the part number and “remembering what the extensions mean.”

Connectors and switches and the like are where things can get ugly, quickly. Consider a board-mount male XLR connector. Neutrik has a dozen choices, Switchcraft has many more, and there are other vendors. Most footprints (and panel cut-outs) are incompatible. So calling a library part XLR-M is clearly insufficient, unless you know you will choose exactly one type of this part and never consider another. What I’ve done is to rely on my parts list, Kicad’s symbol browser and its description field and call the part by its manufacturer’s part number. I am familiar enough with Neutrik’s parts to know that the NC3MAH is a board-mount right-angle male XLR connector. What about JB15LPF-JF? Well, my parts list tells me that’s an NKK momentary pushbutton switch with a green LED. Since my parts list doesn’t have every imaginable switch, this is manageable.

Variants and Families and Part Numbers and Symbols

Above I mentioned that my library has the LM317T and LM317EMP devices. Two symbols, two distinct devices … but two company part numbers? Yes, but — I use the part number variant field to distinguish between the two. Thus, LM317T has a part number A-1000-0 and LM317EMP has the part number A-1000-1. This is trivial, I admit, but there is a rule here. A variant indicates that all of the parts with the same category and part number are the same except that they vary in exactly one respect. In the case of our voltage regulators, that one variable is the package. In this manner, one might wish to define a part number for a microcontroller with 32 kB flash and its pin-compatible smaller brother with 16 kB flash. The two can be distinguished by the variant.

Now, the big one: what to do about parts such as resistors, where an entry for each individual value, package and tolerance would quickly cause the library to grow to a ridiculous size? (I should note that I worked for one employer whose library really did include one entry for each resistor value, package and tolerance that they used.) This is where the concept of a “family part number” comes in.

The idea is that the category and the part number indicate a family of parts which vary only in value. The family is represented by only one symbol. Consider the standard 0805 1% resistor. We create a symbol called R0805_1%. Its Footprint field is populated in the usual way. Its custom PN field has B-1000 entered (no variant included). The Value field is left at the default (which is the part name, in this case R0805_1%).

As the engineer places the resistors on the schematic, s/he must edit the part’s Value field appropriately. What does this mean? In my Master Parts List, for these resistors the variant part of the part number is the value. A 100Ω 0805 1% resistor is part number B-1000-100R, so the user enters 100R in the Value field. A 2.67kΩ resistor in that family is part number B-1000-2k67, and as such 2k67 is entered in the value field. And so forth.

When a BOM is exported from EESchema using the bom2csv.xslt script, the resulting CSV file will include the part number and the value for each part in the design. To get a final BOM, with orderable part numbers and manufacturer names and quantities for each part, I parse the CSV against the Master Parts List with Python script. The script “knows” that for parts in the Resistors category B, it must concatenate the part Value with the PN to get the Part Number key into the Parts List, and from there it can pull the manufacturer part number. Parts such as ICs, where the “family” concept isn’t used, have the full Part Number key already from the part’s PN field.

There are likely better ways to build the final BOM. One would be to have the Python script work directly on the schematic, rather than rely on the XSLT script to create the intermediate BOM. Another way would be for the Master Parts List to be built in a proper SQL database, which would import the Kicad CSV BOM and work on it without a Python script.

Kicad library paradigms

The topic of how Kicad (and indeed, any other EDA package) libraries should be organized comes up regularly on forums such as the Kicad User forum. There are many opinions, and user preference seems to be mostly based on experience with previously-used systems. The preference also seems to be split down a “professional” versus “hobbyist” point-of-view. This post will attempt to present the two prevailing preferences for Kicad library organization. After that, I will explain the basic system I have created for my own use.

Kicad Libraries, an overview

As of the current stable version of Kicad, 4.0.6, Kicad’s libraries are divided into three separate types:

Schematic symbol libraries (which have a .sch file extension) hold all of the symbols the designer can put on a schematic using EESchema.

Footprint libraries (which have a .pretty file extension, and are actually directories which contain the footprints, which have a .kicad_mod file extension) hold the footprints which are used with pcbnew to define how a real component is attached to the board and connected to other parts.

3D model libraries aren’t really libraries, rather, they are just collections of 3D models in VRML format, and for nightly builds also STEP.

These three library types are loosely connected. Each schematic symbol has a “Footprint” field, which can be populated or not. A part might come in more than one footprint, so a user might wish to not have the library symbol include a default. As for footprints, it should be obvious that common footprints are used by thousands of devices, so having a generic SOIC-8 footprint is more useful than having a TL072-SOIC-8 footprint. Finally, all footprints have a 3D Model field, which calls out such.

Users can decide how to organize their libraries. One might reasonable decide to have exactly one schematic library and one footprint library, and those libraries include only parts that have been vetted and put onto an approved parts list. Others might prefer to have a “digital” library, an “analog” library, a “passives” library and so forth for schematic symbols, and an “IC” library, a “passives” library, a “connectors” library and so forth for PCB footprints. Kicad is flexible, indeed agnostic, in this respect.

Paradigms for Kicad libraries

Since schematic symbols in libraries are not required to have a populated footprint field, Kicad allows for essentially two separate library paradigms, which I will call the “CvPCB flow” and the “atomic library” concept.

CvPCB Flow

This is named for the Kicad tool CvPCB, which is used to map footprints to schematic symbols prior to generating a netlist for pcbnew.

Many users prefer to draw a schematic without concern for the actual components to be used on the board. For example, a user designing an op-amp circuit may wish to place a generic op-amp symbol on the sheet, and then choose generic resistor and capacitor symbols to complete the design. Before layout, obviously footprints must be chosen, so the CvPCB tool is run to do this association. The user may select DIP-8 for the op-amp and standard ¼-watt through-hole parts for the resistors and a standard through-hole ceramic part for the capacitors. (Part values are uninteresting for the layout, so it doesn’t much matter whether the op-amp is a TL072 or an NE5532.) After associating all symbols with a footprint, CvPCB back-annotates the selections to the schematic. The footprint field in each symbol is populated with what was chosen. Then a netlist is generated and pcbnew is launched. The netlist is imported, and the layout starts with all of the chosen footprints.

This flow has advantages. One is that the designer may not know exactly what op-amp is being used, or whether through-hole or surface-mount passives are going to be used. This flexibility is prized by hobbyists.

This flow has disadvantages. The main one, in my view, is that it is utterly disconnected from any reasonable way of generating a bill of materials. Matching the resistors and op-amps put on the schematic to something one can actually buy requires generating a generic BOM from Kicad and then manually editing it to match parts from various vendors. And this manual parts matching occurs for every design, every time. For the hobbyist doing one board design a year, this inefficiency is probably acceptable.

Atomic PARTS (or components) Libraries

“Atomic parts” is a term used to indicate that the symbol in the schematic library is more than just something generic without footprint or part-number information. It means that the symbol and the footprint (and the 3D model) are combined into one inseparable unit. All symbols have a footprint pre-selected. Ideally, each symbol includes a custom “Part Number” field. This part number field is critical, as it is the hook into a parts list database. This database is not part of Kicad, and can be as simple or complex as the user requires.

A generic “dual op-amp” symbol is no longer allowed. Instead, the user must create, for example, an OPA1652AID symbol with the SOIC-8 footprint set. A USB Type B jack is similar, in that it will explicitly call out the proper footprint. Rather than generic “resistor,” the library will contain RES_0805_1%, indicating that the part is the 0805 size and has a tolerance of 1%. Value of the resistor is given in the symbol’s VALUE field, as one might expect.

The disadvantage to this paradigm is that parts have to be fully defined before the design can begin. The professional user will argue, though, that this requirement is really an advantage. When an OPA1652AID is placed on the schematic, pcbnew already “knows” that it uses the SOIC-8 package. The BOM generated by EESchema also has the correct part number; there is no need to look up parts and create the BOM by hand. The hard work of that parts lookup and vetting is done once and is then used for each design. It is tedious work that is not repeated.

In a following post, I will explain the simple atomic parts library system I’ve created for my own use.

My Kicad Libraries

Kicad Libraries

I have created a set of Kicad schematic and footprint libraries. The library archive is available here.

These instructions are for Mac users.

After downloading, copy the archive to your user application support directory at /Users/YourAccountName/Library/Application Support/ and unarchive it (double-clicking in the Finder suffices). It will create a folder in the application support directory called kicad. This is the standard directory for Kicad libraries. Some users might wish to put the libraries into the global library directory, /Library/Application Support/kicad.

Inside that directory are the schematic symbol libraries (in library), the footprint libraries (in modules) and any 3D models I might have (in modules/package3d). The scripting directory has some plug-ins, notably the Python scripts which are used to generate footprints.

The plugins directory has some XSL scripts, most notably the bom2csv.xsl script which is used to generate bills of material from EESchema.

The template directory has a couple of default project templates.

The help directory has the PDF-format manuals for all of the Kicad programs.


Setting up EESchema to recognize schematic libraries

You need to tell EESchema where to find the schematic symbol libraries. From EESchema’s main menu, choose Preferences => Component Libraries. A dialog pops up:

kicad-schematic-library-list

Initially it might be populated by Kicad default libraries.  (You may have gotten dire warnings from EESchema when you first launched it.) Go through and select and delete each of those default libraries.

Next, make sure that the libraries you unarchived earlier are on one of the paths listed under “Current search path list.” If not, add the path to the search list by hitting the “Add” button next to “User defined search path” and mousing around to that directory (in my case, it’s /Users/andy/Library/Application Support/kicad/library).

Then, hit the “Add” button next to the list of Component library files and selecting each library.  Now all of the libraries should be available to use for schematic entry.

Please note: As you add components to the schematic, they will also be added to a file created automagically in your project directory called projectname-cache.lib. DO NOT delete this file! If you do, all of the symbols you added to the design will be lost. (Unlike pcbnew, the current eeschema file format does not embed the symbols in the sheet schematic file, and instead uses this cache. The Kicad developers indicate that they will revise the schematic file format to eliminate this weirdness and embed the symbol in the schematic file.)

Once the library list is set up, you should be able to browse the libraries from within EESchema and place the symbols onto your sheets.


Setting up the Footprint Libraries for use with pcbnew

You tell pcbnew where to find footprints by setting an environment variable and then using that environment variable in a list called a “Library Table.” This sounds complicated but it’s very simple.

First, we’ll set the environment variables. These are mainly useful for those who use Kicad on different machines which might have different library locations, for example working on a Mac and then on a Windows machine. From the Kicad project manager main menu, choose Preferences => Configure Paths. The following dialog pops up:

kicad-env-var-path-config

For our purposes, ignore the KIGITHUB line; that is useful if one wishes to access the community footprint libraries that are served by Github.

The KISYSMOD and KISYS3DMOD paths must be set to the directories where you find the footprints and the 3D models, respectively. You can see that here I’ve set them to the correct locations. If they are not correct, or do not exist, then double-click on an incorrect path and enter the correct one. Click OK to save.

Next, you need to create or modify a library table. This is the file that maps the footprint library locations to a pointer that is used in pcbnew to find the footprints. Again, this is all so that you can store the libraries anywhere in the file system on any computer, and as long as the entries in the file table are correct, pcbnew can find the footprints.

By default, the footprint library table is called fp-lib-table and it lives in the directory /Users/yourname/Library/Preferences/kicad. It is a text file and can be opened and changed by any editor. My current library table file, which references all of my PCB libraries, is here.

Modifying the library table is easy. From the pcbnew main menu, choose Preferences => Footprint Libraries Manager. (You may also prefer the Wizard.) This opens a dialog like this:

kicad-library-tables-manager

Here you the location and the contents of my library table. As of Kicad stable 4.0.0, the footprint library is actually a directory with the suffix “.pretty,” and inside that directory are the individual footprints within that library.

For each library, you give it a “nickname,” which is a short name for the library. I recommend making the nickname the same as the library directory sans the .pretty suffix. (Don’t confuse yourself.) If the nickname is the same on all of your different machines, pcbnew will never have a problem finding the library.

Next, note the library path includes the ${KISYSMOD}/ prefix. This text string invokes the environment variables for the library location, and it’s the hook which lets you put the library anywhere in the filesystem and pcbnew will be able to find it. The environment variables are shown at the bottom, and you can change them as you need.

For the most part, “Plugin Type” will be Kicad, which is the “.pretty” format. “Legacy” libraries are in an ancient format Kicad used to use and is now deprecated. Those libraries can be read but not modified. (If they are modified, they are automatically upgraded to the new format.) You can also directly use, but not modify, EAGLE- and gEDA-format footprint libraries. (Note that you cannot use EAGLE or gEDA symbol libraries in your schematics.)

Ignore the “options” for now. And if you prefer, you can enter a short description of the libraries, in case the name itself is insufficient.

Once the library table is set up, it can be used when importing a netlist generated by EESchema, as long as the symbols in the schematic have proper “footprint” entries (all of mine do). If you create your own symbols, it is not strictly necessary to embed a footprint link in them; you can use the CvPCB program within EESchema through the Tools => Assign Component Footprint” menu option. But I don’t recommend this design flow. Create symbols with reasonable names that somehow indicate footprint, and then marry the footprint to the symbol by making sure that the symbol’s “Footprint” field has a valid entry.


Generating a Bill of Materials

You will note that each of the symbols library has a custom part number field called PN, and that field is always filled. This field holds a key into a master parts list I created. The parts list is here, as a zipped Apple Numbers spreadsheet, and here as a zipped CSV export of that database.

A python script called bomgen.py is used to parse the BOM exported from EESchema and look up the parts against the CSV parts list. Put the script and PartsDatabase.csv into the same directory as the CSV BOM exported by EESchema. Run the script from the Terminal like such:

$ python bomgen.py DesignBOM.csv PartsDatabase.csv

You will see messages as the BOM is parsed, and will be greeted at the end with a success or failure message. The result is a CSV file called FinalBOM.csv.

New IR remote volume control

We use a Mac mini as our home theatre hub. Its HDMI output connects to the TV, and its analog audio output on the 1/8″ jack connects to a pair of self-powered studio monitors. That all works well.

Then the optical drive in the Mac decided to stop working, so I connected the old DVD player to the TV. But the DVD player’s audio cannot be (easily) routed to the studio monitors; it has to go through the television.

The TV has a digital-audio output, so I bought a cheap Monoprice DAC and connected its TOSLINK input to the TV and its RCA audio outs to the monitors. That works, except that the TV’s digital-audio output doesn’t follow the TV’s volume control. I guess they expect users to connect it to a receiver, which would obviously have its own volume control with remote.

So the solution? A simple IR remote volume control, based on the TI PGA2320. It uses the THAT 1240 dual differential line receiver for the balanced audio input and a pair of THAT 1646 differential line drivers for the balanced audio output. A Silicon Labs C8051F314 micro runs the show, managing a Vishay TSOP34838 IR receiver, a Newhaven Displays NHD-0216HZ-FSW-FBW-33V3C 16-character-by-two-line LCD, and a Bourns PEC09-2320F-S0015 rotary encoder. It all fits into a Hammond 1455N1201BK enclosure.

All programming was done in C, with the Keil compiler which is part of the Silicon Labs Simplicity Studio tools. The PCB was designed using very recent builds of Kicad. Both tools run on Mac OS X.

IR Remote Test Setup

IR Remote Top View

IR Remote front

Nightly builds of Kicad for OS X are available

The Kicad devs have packaged precompiled binaries for OS X, and they are available here.

They are nightly builds, generally considered “bleeding edge,” but they will typically run well.

The main .dmg contains the application and schematic libraries, and assumes you will use github to pull footprints. The -extras .dmg contains the footprint libraries so you can install them locally. You should probably install them locally.

At some point they will decide that something is a stable release.

Hello world!

I am an electronics engineer, employed by a local company, designing very cool stuff. But on occasion I have an itch that has to be scratched, and the only way to scratch that itch is to design some little bit of electronics.

This occasionally-updated blog will have information about these little designs. Right now, I don’t know whether the designs will be fully open source or what. I may decide to make the designs available as kits, or perhaps just make PCBs available for purchase. It all depends on the time I have available.

What you might find interesting is that I do as much of the design work on Mac OS X, not Windows or Linux. (There are exceptions, which will be noted when I get to them.)

For the physical designs (schematics and PCB layout), I have been successfully using the open-source Kicad suite. I have been building the tools from the main Kicad bazaar “product” branch, but there are a couple of developers working on the creation of OS X binaries. I will post links to those binaries as they become available (which should be any day now).

For 8051 microcontroller design and development, I greatly prefer the Silicon Labs devices. They are inexpensive, they can be programmed in-circuit with a $39 dongle, and they work as advertised. SiLabs also offers excellent support, and they provide free software tools. Their Eclipse-based Simplicity Studio runs on OS X, Linux and Windows and it’s pretty good.

That’s all for now. More to come …