Friday, 24 June 2016

PHP: CSS colours (colors): css_colours.php

Here's my first bit of code.

Actually, web accessibility has nothing to do with this! It's more about convenience (though some of my modules do make use of this as a resource).

So, save this as "css_colours.php". Yes, for my American friends, you'll need to learn how to not spell quite so lazily... :-P .

You'll note there's no ?> at the end of the code. This is because it ensures that, as include'd (or require'd), the parent file will stay in PHP mode and not drop back to HTML mode (which may not happen, depending on various things... but it at least apparently removes the possibility!

<?php

$css_colours = array (
    'AliceBlue' => '#F0F8FF',
    'AntiqueWhite' => '#FAEBD7',
    'Aqua' => '#00FFFF',
    'Aquamarine' => '#7FFFD4',
    'Azure' => '#F0FFFF',
    'Beige' => '#F5F5DC',
    'Bisque' => '#FFE4C4',
    'Black' => '#000000',
    'BlanchedAlmond' => '#FFEBCD',
    'Blue' => '#0000FF',
    'BlueViolet' => '#8A2BE2',
    'Brown' => '#A52A2A',
    'BurlyWood' => '#DEB887',
    'CadetBlue' => '#5F9EA0',
    'Chartreuse' => '#7FFF00',
    'Chocolate' => '#D2691E',
    'Coral' => '#FF7F50',
    'CornflowerBlue' => '#6495ED',
    'Cornsilk' => '#FFF8DC',
    'Crimson' => '#DC143C',
    'Cyan' => '#00FFFF',
    'DarkBlue' => '#00008B',
    'DarkCyan' => '#008B8B',
    'DarkGoldenRod' => '#B8860B',
    'DarkGray' => '#A9A9A9',
    'DarkGrey' => '#A9A9A9',
    'DarkGreen' => '#006400',
    'DarkKhaki' => '#BDB76B',
    'DarkMagenta' => '#8B008B',
    'DarkOliveGreen' => '#556B2F',
    'Darkorange' => '#FF8C00',
    'DarkOrchid' => '#9932CC',
    'DarkRed' => '#8B0000',
    'DarkSalmon' => '#E9967A',
    'DarkSeaGreen' => '#8FBC8F',
    'DarkSlateBlue' => '#483D8B',
    'DarkSlateGray' => '#2F4F4F',
    'DarkSlateGrey' => '#2F4F4F',
    'DarkTurquoise' => '#00CED1',
    'DarkViolet' => '#9400D3',
    'DeepPink' => '#FF1493',
    'DeepSkyBlue' => '#00BFFF',
    'DimGray' => '#696969',
    'DimGrey' => '#696969',
    'DodgerBlue' => '#1E90FF',
    'FireBrick' => '#B22222',
    'FloralWhite' => '#FFFAF0',
    'ForestGreen' => '#228B22',
    'Fuchsia' => '#FF00FF',
    'Gainsboro' => '#DCDCDC',
    'GhostWhite' => '#F8F8FF',
    'Gold' => '#FFD700',
    'GoldenRod' => '#DAA520',
    'Gray' => '#808080',
    'Grey' => '#808080',
    'Green' => '#008000',
    'GreenYellow' => '#ADFF2F',
    'HoneyDew' => '#F0FFF0',
    'HotPink' => '#FF69B4',
    'IndianRed' => '#CD5C5C',
    'Indigo' => '#4B0082',
    'Ivory' => '#FFFFF0',
    'Khaki' => '#F0E68C',
    'Lavender' => '#E6E6FA',
    'LavenderBlush' => '#FFF0F5',
    'LawnGreen' => '#7CFC00',
    'LemonChiffon' => '#FFFACD',
    'LightBlue' => '#ADD8E6',
    'LightCoral' => '#F08080',
    'LightCyan' => '#E0FFFF',
    'LightGoldenRodYellow' => '#FAFAD2',
    'LightGray' => '#D3D3D3',
    'LightGrey' => '#D3D3D3',
    'LightGreen' => '#90EE90',
    'LightPink' => '#FFB6C1',
    'LightSalmon' => '#FFA07A',
    'LightSeaGreen' => '#20B2AA',
    'LightSkyBlue' => '#87CEFA',
    'LightSlateGray' => '#778899',
    'LightSlateGrey' => '#778899',
    'LightSteelBlue' => '#B0C4DE',
    'LightYellow' => '#FFFFE0',
    'Lime' => '#00FF00',
    'LimeGreen' => '#32CD32',
    'Linen' => '#FAF0E6',
    'Magenta' => '#FF00FF',
    'Maroon' => '#800000',
    'MediumAquaMarine' => '#66CDAA',
    'MediumBlue' => '#0000CD',
    'MediumOrchid' => '#BA55D3',
    'MediumPurple' => '#9370D8',
    'MediumSeaGreen' => '#3CB371',
    'MediumSlateBlue' => '#7B68EE',
    'MediumSpringGreen' => '#00FA9A',
    'MediumTurquoise' => '#48D1CC',
    'MediumVioletRed' => '#C71585',
    'MidnightBlue' => '#191970',
    'MintCream' => '#F5FFFA',
    'MistyRose' => '#FFE4E1',
    'Moccasin' => '#FFE4B5',
    'NavajoWhite' => '#FFDEAD',
    'Navy' => '#000080',
    'OldLace' => '#FDF5E6',
    'Olive' => '#808000',
    'OliveDrab' => '#6B8E23',
    'Orange' => '#FFA500',
    'OrangeRed' => '#FF4500',
    'Orchid' => '#DA70D6',
    'PaleGoldenRod' => '#EEE8AA',
    'PaleGreen' => '#98FB98',
    'PaleTurquoise' => '#AFEEEE',
    'PaleVioletRed' => '#D87093',
    'PapayaWhip' => '#FFEFD5',
    'PeachPuff' => '#FFDAB9',
    'Peru' => '#CD853F',
    'Pink' => '#FFC0CB',
    'Plum' => '#DDA0DD',
    'PowderBlue' => '#B0E0E6',
    'Purple' => '#800080',
    'Red' => '#FF0000',
    'RosyBrown' => '#BC8F8F',
    'RoyalBlue' => '#4169E1',
    'SaddleBrown' => '#8B4513',
    'Salmon' => '#FA8072',
    'SandyBrown' => '#F4A460',
    'SeaGreen' => '#2E8B57',
    'SeaShell' => '#FFF5EE',
    'Sienna' => '#A0522D',
    'Silver' => '#C0C0C0',
    'SkyBlue' => '#87CEEB',
    'SlateBlue' => '#6A5ACD',
    'SlateGray' => '#708090',
    'SlateGrey' => '#708090',
    'Snow' => '#FFFAFA',
    'SpringGreen' => '#00FF7F',
    'SteelBlue' => '#4682B4',
    'Tan' => '#D2B48C',
    'Teal' => '#008080',
    'Thistle' => '#D8BFD8',
    'Tomato' => '#FF6347',
    'Turquoise' => '#40E0D0',
    'Violet' => '#EE82EE',
    'Wheat' => '#F5DEB3',
    'White' => '#FFFFFF',
    'WhiteSmoke' => '#F5F5F5',
    'Yellow' => '#FFFF00',
    'YellowGreen' => '#9ACD32');

Oh, the inaccessible humanity!

Background

I've recently started a new position as an accessibility tester. This means testing web-based software and web pages against the Web Content Accessibility Guidelines (https://www.w3.org/TR/WCAG20/).

An obsession???

I've been told by my lovely other half that I'm a bit obsessed by WCAG. It's hardly surprising, really... many of the guidelines in WCAG are applicable to me in one manner or another! (I should point out that by no means all of them, and some of them that are applicable you might be surprised by!).

It's all about the audience!

But it's also a question of caring for others. If a web designer fails to take into account people with various access issues, they're effectively cutting off those people from using your site, meaning that what you want to convey to them is missed - but just to those people.

Exclusion is a pretty big experience that many people with disabilities have, frequently, regularly and often very subtly. Consider a wheelchair user, who has to use a "side" entrance to access a ramp to enter a building. It might take them an extra couple of minutes when this happens... but if this happens many times in the course of a day, that time adds up. And that's time these people are (in our terms) "unproductive" - but this isn't their fault (it's ours because our culture did not consider just putting said ramps in place at the front of buildings to begin with!)

The same is true of web-based information. If your site comes at the top of google rankings for a particular set of search terms, but some users can't use your site, these users have to go back and find other resources (probably the second-top ranking site). If that site also suffers from the same problem of inaccessibility, that can be repeated.

If no-one bothers, then how do these people access that information? Given the big shift to on-line publication, these people will end up with the digital equivalent of stairs at the front of a building!

OK, it's about you, too!

You can see from this, that it's about you, the web author, as well. If you have a pay-per-view site, but some users can't use your site, you're cutting off a portion of your potential revenue stream.

Some think this is not a big deal. But apparently it is, as this example demonstrates (for the record, I neither endorse nor dis-endorse any of the companies listed).

An example: Paypal and "bootstrap"

The people at Twitter make a web page framework called "bootstrap". Out-of-the-box bootstrap is not WCAG compliant... and while it can be made kind-of compliant, it is difficult to do so (lots of things to override, modify, etc., for it all to happen).

Paypal wanted to use bootstrap. Most of their competitors also use bootstrap. This means that the vast majority of on-line sales are not able to be accessed by, for example, vision-impaired people.

Paypal have created their own bootstrap "fix". It is mostly WCAG compliant - it has some bits needing to be ironed out, but it is considerably better than native bootstrap. It's cost them a considerable amount of investment to do so... but their sales projections are about 10% higher than would otherwise be the case: this system gives them a significant competitive advantage! The investment will pay for itself in about a year or so.

On-line examples

I often make use of code from the net in my projects. If someone has solved the problem already - and is freely making their code available for use! - why re-invent the wheel?

However, a very large proportion of these examples don't include accessibility considerations (I'm talking PHP, JavaScript, CSS and HTML in particular here). Which means they haven't really solved the problem.

My response?

I'm going to re-invent the wheel. With accessibility considered.

I'm going to start publishing some updated examples and some (in particular PHP) modules that will help make sites to not be inaccessible.

Note I'm not saying that it will make your site accessible! Some guideline rules (e.g. 2.1.2: "no keyboard trap") cover the entirety of the page, so just dropping a module or two into the middle of it won't make the page accessible.

What these modules will do is to ensure that the places where they are used will meet the requirements as much as possible.

Oh, and each module will also have a list of sufficient techniques that they satisfy (in case you wish to make a conformance claim).

Monday, 4 January 2016

Updating our Christmas lights

Part #3

Firmware

The firmware (embedded software within a microprocessor/microcontroller) is done. Well, the first cut, anyway. As is the first cut of the board.

But I have a huge problem to figure out: how to test the firmware? I particularly wish to test the I2C interactions, as I've never written full-on I2C interaction code (though, in truth, I've pulled much from a Microchip PIC application note... but the issue is that the AN is written for a different chip and the memory layout is different, resulting in different code in many places!).

The cause of my dilemma is that the simulator within the MPLAB X development environment does not include simulation of signal-level communications devices, including I2C - meaning the first time my firmware code looks to verify a response from the target memory, an infinite loop occurs as the response is never received. I can prod the I2C module by injecting anticipated target memory responses, but that's not the same. And my preference is to test the firmware separate to the hardware if at all possible - so that any issues with the board can be pinned down to the board specifically, rather than a possible combination of hardware/firmware errors.

I've looked around to see if there were packages for my particular controller of choice for this circuit, but alas there aren't (though one company did have a nice special that ended early this morning our time on similar but not quite the same chips, so I didn't buy it... Part of me is regretting that already since some of the other devices I'd been looking at using the in past were in that deal, and the package included I2C simulation specifically with one of the EEPROM memories I'm looking at).

Another alternative is to write my own, possibly using the VLAB tools (written by a former workplace of mine, ASTC). The only problem there is that I'd still have to write a whole bunch of models for each of the PIC on-chip peripherals, and then I'd have to test the models individually in order to ensure the models were accurate before running my potentially dodgy code over an integrated set of them.

Alternately, I just do what I'd least like to do: finalise the board and build it (using something like ZIF sockets, particularly for the PIC chip to allow its extraction for re-programming). My PIC programmer, however, doesn't include the capacity to program the I2C EEPROMs... so I'll also need to buy a programmer board for them, too. Found a free board/PIC-based program at http://openprog.altervista.org/OP_eng.html, so have downloaded it and will proceed to get the components, make that board and see how I go.

My plan is to program one address in one chip, and write a small program that simply extracts that one value, and dump that 8-bit value out of port C on the PIC (via a bunch of LEDs). If that's successful, then I can proceed with the full version as the full firmware basically does the same job throughout.

Moreover, the 6 hardware PWM modules are pretty easy to configure, and the interrupts for the software PWM and the 0.56s and 2s periodic flashing lights I can simulate using the package (I will need to inject the I2C responses in order to get to that part of the code, though).

Saturday, 2 January 2016

Updating our Christmas lights

Part #2

PWM configuration

In my previous post, I'd selected the PIC16F18344 as the baseline controller, but mentioned it had an issue with the internal EEPROM memory (that's memory that isn't erased when the controller loses power... an important consideration since we run our lights off a timer switch, so when they go off at night the controller will lose power!): it had nowhere near enough.

Running the controller flat out at 32MHz internal clock (instructions are executed every 4 clock cycles) means that the PWM modules can have a base frequency of not quite 500Hz (488.28125Hz, actually). This is the TMR2 (timer 2) module with the 1:64 prescaler and rolling over once every 256 cycles (since TMR2 is an 8-bit timer) at that /64 clock. TMR2 can be used as a period timer for the PWM modules, and 488Hz gives a period far shorter than the human eye's sample rate (PWM period is approx 2ms, human eye's sample rate is approx 32ms).

Given that I'm after 8 PWM outputs, 2 of which need software interrupt control, I need to run the chip as fast as possible, otherwise there'll be out-of-synch issues with the software PWM timing. Given that the PWM values need to be extracted from somewhere, I can of course compensate for that to some extent by factoring in a small buffer for values between full off and full on.

Here's what the 8 PWM outputs will do:
  • CCP1 (put into PWM mode) will run the blue section for blue/green/red/orange sets
  • CCP2 (put into PWM mode) will run the green section for blue/green/red/orange sets
  • CCP3 (put into PWM mode) will run the red section for blue/green/red/orange sets
  • CCP4 (put into PWM mode) will run the orange section for blue/green/red/orange sets
  • PWM5 (dedicated PWM module) will run section 1 of the icicle lights
  • PWM6 (dedicated PWM module) will run section 2 of the icicle lights
  • software PWM using TMR1 will run one set of monochrome lights
  • software PWM using TMR3 will run a second set of monochrome lights
The CCP and dedicated PWM modules have dedicated outputs, so there's no need to handle any interrupts for them. The software controlled ones, though, operate off 3 interrupts:
  • TMR1's and TMR3's interrupts fire when they overflow. Thus, with each timer pre-loaded with a duty-cycle value, the overflow interrupt handler toggles a separate GPIO pin low.
  • TMR2's interrupt also fires on overflow; this overflow co-incides with the CCP and PWM modules also beginning a new period and their dedicated hardware PWM outputs going high. So the TMR2 interrupt also fires a handler to set the TMR1 and TMR3 GPIO pins high.
Note that because the TMR1/3 and TMR2 interrupts are likely to be at different times, the TMR1 and TMR3 interrupts will fire between TMR2 interrupts (since the actual full count periods of the 3 timers is the same)... meaning those outputs will toggle like a PWM output should. There is a caveat, though: if the duty cycle values are 0 or 255, then the outputs are set and left alone.

Port C on the PIC16F18344 is an 8-bit port, and can easily be configured to have the 6 hardware PWMs route directly out, so will simply manually trigger RC6 and RC7 off the software PWMs. So there we go: 8 dedicated PWM output pins!

Periodic half-duty-cycle flashing




I've also had a thought about periodic flashing lights of a different sort: every half second and every 2 seconds. These'll run off TMR5, which will roll over every 0.5s, and an external counter in a variable will count every time it rolls over; once this count hits 4, the 2s output is toggled. No interrupts will handle this, as the main program is otherwise just clearing the watch-dog timer and getting set up for the next duty cycle values for the PWMs, so having it poll the TMR5 overflow flag status bit will be OK as well (none of the other tasks - including the interrupts - actually takes more than a few milliseconds, so you won't see any deviation in the period. I hope).

Will have to sort out which pins to use, once I solve the memory issues...

Memories, all alone with my memories...

(sorry, couldn't resist that).

I've discovered that Microchip/Atmel make a nice set of EEPROM chips with an I2C interface. The chips - regardless of the amount of memory on board - have only 8 pins. More importantly, any up to the 512kbit memories have 3 of their pins able to set a hardware address, so that you can have 8 different chips on the one I2C bus which can be selectable by the I2C control word sent as the first part of the I2C transaction. 8 EEPROM chips: one for each PWM channel! Sweet.

And, with 512kbits and 16-bit duty cycle values per PWM channel, I've got 32768 separate values I can use.

I'm not sure I want to have a re-load of the duty cycle every time the PWM rolls over. That gives me a complete pattern cycle of only just over a minute!

A better option is to have it trigger over 10th of a second, or as close to possible. This allows for significantly fast flashing if I need, but also allows for less chunky steps in the gradual bright/dim pattern as well (some early controllers with only 4 bit PWM resolution clearly show the steps and they look horrible).

I can configure TMR0 of the PIC16F13844 to fire every 0.098s, which is close enough. 512kbit EEPROMs thus give me a full pattern cycle of around 57 minutes. Nice :-) .

The PIC16F18344 defaults to the SCL I/O pin on RB4 and SDA on RB6 (clock and data lines of the two-wire I2C bus). That leaves me RB5 and RB7 to use for the 0.5s and 2s period outputs, and leave port A completely free for other stuff if I need (though RA3 I'll use as a manual reset input - probably not used on the final product but at least I can use it during hardware debugging!).

Off to design the circuit, board layout and firmware for the PIC16F18344. Stay tuned...