Typing out MG84FL54-specific registers

In the next part we will start using the functionality specifically
provided by our microcontroller, the Megawin [MG84FL54BD][]. It has
quite a few special function registers (SFRs) about which SDCC’s
standard headers know nothing. So we will need to list them. They go in
the controller-specific header file.

[MG84FL54BD]: http://www.megawin.com.tw/megawin_EN/ProductShow.asp?ID=175

Megawin’s SFRs come in two varieties. There are ordinary SFRs located in
the direct addressable memory at `0x80` through `0xFF`; and there are USB
SFRs at extended memory addresses `0xFF00` through `0xFFFF`.

Many registers are bit masks (with each bit having separate meaning),
and a few are bit-addressable (the controller can access an individual
bit without using bitwise operations).

The syntax for a direct SFR is:

```c
__sfr __at(0xD5) KBPATN;
```

(It is technically a bit mask register, but its bits don’t have
individual names in the manual so we don’t bother.)

For a bit mask register, we want to define symbolic constants for each
significant bit:

```c
__sfr __at(0xAD) AUXIE;
enum { EUSB = 0x80, ETWSI = 0x40, EKB = 0x20, ESPI = 0x01 };
```

For bit-addressable registers, SDCC provides a mechanism of giving names
to each individual bit:

```c
__sfr __at(0xE8) P4;
__sbit __at(0xE8) P4_0;
__sbit __at(0xE9) P4_1;
__sbit __at(0xEA) P4_2;
__sbit __at(0xEB) P4_3;
```

For `xdata` SFRs, there is no special syntax in SDCC. So we need to
declare them as absolute address `xdata` variables, with a `volatile`
qualifier so that the optimizer does not meddle with them:

```c
volatile unsigned char __xdata __at(0xFFC0) DCON;
```

USB SFRs can also be bit mask registers.

But it’s a bit tiring to type out all this boilerplate so let’s employ
some preprocessor magic. We would like the following syntax:

```c
SFR(0xD5, KBPATN); // byte SFR
SFR_(0xAD, AUXIE, EUSB, ETWSI, EKB, _, _, _, _, ESPI); // bitmask SFR
BIT_SFR(0xE8, P4, _, _, _, _, P4_3, P4_2, P4_1, P4_0); // bit-addressable SFR
XSFR(0xFFD8, UADDR); // byte xdata SFR
XSFR_(0xFFC0, DCON, _, _, _, SRWKP, EP3DIR, _, _, _); // bitmask xdata SFR
```

To achieve this, we define a few macros. The easy ones:

```c
#define SFR(address, name) __sfr __at(address) name
#define XSFR(address, name) volatile unsigned char __xdata __at(address) name
```

Bit masks:

```c
#define BITS(b7, b6, b5, b4, b3, b2, b1, b0) \
    enum { b7 = 0x80, b6 = 0x40, b5 = 0x20, b4 = 0x10, \
        b3 = 0x08, b2 = 0x04, b1 = 0x02, b0 = 0x01 }
#define SFR_(address, name, b7, b6, b5, b4, b3, b2, b1, b0) \
    SFR(address, name); \
    BITS(b7, b6, b5, b4, b3, b2, b1, b0)
#define XSFR_(address, name, b7, b6, b5, b4, b3, b2, b1, b0) \
    XSFR(address, name); \
    BITS(b7, b6, b5, b4, b3, b2, b1, b0)
```

Bit-addressable:

```c
#define BIT_SFR(address, name, b7, b6, b5, b4, b3, b2, b1, b0) \
    SFR(address, name); \
    __sbit __at(address) b0; \
    __sbit __at(address + 1) b1; \
    __sbit __at(address + 2) b2; \
    __sbit __at(address + 3) b3; \
    __sbit __at(address + 4) b4; \
    __sbit __at(address + 5) b5; \
    __sbit __at(address + 6) b6; \
    __sbit __at(address + 7) b7
```

Now we only have to define the magic underscore “don’t care” macro. We
want it to expand each time into a unique unused identifier. Luckily,
the SDCC compiler has an extension macro `__COUNTER__` just for this
purpose.

```c
#define CATENATE(a, b) a ## b
#define UNUSED(x) CATENATE(UNUSED_, x)
#define _ UNUSED(__COUNTER__)
```

(Two auxiliary macros are needed to force expansion of `__COUNTER__`
before `##` catenation.)
## Reboot on any key

While trying to implement the basics of USB, I got tired of continuously
toggling the safety DIP (reboot as ISP → reflash → reboot normally → it
doesn’t work as expected → repeat). Moreover, it is said that DIP
switches have a limited resource. Would be much easier if I could reboot
to ISP mode with a press of a key — we don’t have any use for them yet.

This is where the keypad interrupt comes in handy.

First, we set up the column pins as open-drain outputs:

```c
void keypad_init(void)
{
    P1M0 = 0xFF;
    P1M1 = 0xFF;
    P2M0 = 0xFF;
    P2M1 = 0xFF;
    P3M0 = 0x18;
    P3M0 = 0x18;
```

Then we activate all columns:

```c
    P1 = 0;
    P2 = 0;
    P3 &= 0xE7;
```

And set up the keypad interrupt to trigger when any row goes active:

```c
    KBMASK = 0xFF;
    KBPATN = 0xFF;
    KBCON &= ~PATN_SEL;
    AUXIE |= EKBI;
}
```

The interrupt handler will just reboot to ISP mode.

(While coding this change, I stumbled at the SDK manual calling a few
register bits with inconsistent names (`PATN_SEL` vs `PTNS`, `EKBI` vs
`EKB`). I added aliases for these bits.)