6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Sun Nov 24, 2024 10:47 am

All times are UTC




Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: To build a keyboard…
PostPosted: Tue Aug 27, 2019 3:20 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
There are many different ways to build a keyboard for a homebrew computer.

Some are satisfied with a retro 20-key hexpad for interacting with debug monitors. Some prefer to interface somehow with a modern PC keyboard, despite the frankly absurd contortions of the PS/2 and USB-HID protocols. Other options would include essentially copying the BBC Micro's 73-key design, which interrupts the CPU when a key is pressed, but then the CPU has to scan for and debounce that key by itself. Or a microcontroller could be pressed into service to do that part, leaving only the problems of interfacing to the main CPU, and of programming that microcontroller in the first place.

I'm taking a different tack. I'm going to do the scanning and debouncing entirely in discrete hardware. It looks like it's going to need a couple of dozen ICs, only two of which should cost more than €2 each, and a handful of passive components. By far the biggest costs will be for the keyswitches and PCB, though. With that in mind, accepting sub-par performance for the sake of a few dollars in part count just isn't on. I've taken the Danluu Report into consideration, looked into Cherry's RealKey tech and found it unnecessarily fragile in design (and frankly unambitious in performance), and I'm pretty sure I can do better.

So I'm aiming for sub-millisecond key-down latency, full N-key rollover, and support for a 96-key layout (plenty to support a PC-XT or "pocket computer" type layout). The CPU will be interrupted on both key-down and key-up events, and then it only has to read a scancode from a FIFO and use it to update a bitmap in memory, from whence converting it to ASCII or whatever is straightforward and quick. Should that bitmap need to be refreshed from scratch, no problem, just reset the keyboard hardware, and the current set of pressed keys will then be scanned and presented as key-down events. With any luck, power consumption should also be respectably low, especially when no keys are pressed.

How do I achieve all that without driving myself crazy?

For a start, I do it without involving a microcontroller's finicky vendor toolchains and unknown programming hardware requirements. There is no firmware to install or debug here. So I only need to satisfy myself that the hardware logic is sound. This is the sort of thing I can reasonably verify on a breadboard before ordering the PCB, too. Besides that, I break down the design into three modules: the key-matrix, the debouncer, and the CPU interface.

Starting with that last item first, the keyboard only requires 1 byte of I/O space. Writes go to a configuration register (just a tristate octal D flipflop) which contains the debounce counter value - I can thus tune the keyboard's performance after assembly - and a reset flag. Setting that flag - which is also set by the global reset line - simply causes the keymatrix to read all keys as released while scanning, and also forces the FIFO to the empty state (so any key-up events produced will go into the bit-bucket). The FIFO, a 256x9b device of which one bit of width goes unused, is what services reads from the I/O port, and its "empty flag" produces the /IRQ signal for the device. The scancode itself is 7 bits, and the MSB is used to distinguish between key-down and key-up events.

The keymatrix is fairly conventional for an N-key rollover compatible design. This requires that a diode is placed in series with each individual keyswitch, so that if multiple keys are pressed at once, there is no ambiguity caused by backfeeding along some other row or column line common to them. I've chosen a 6-row by 16-column matrix (ie. 96 key positions), with the columns driven by a pair of 74HC238s, and outputs on the rows sampled through an RC filter each (eliminating microsecond glitches from EMI) to a hex Schmitt-trigger inverter and inputs 2-7 on a 74HC151 multiplexer. Inputs 0 and 1 are left unused, partly because that's convenient for the hex-package of Schmitt-triggers, and partly because that allows more time for an RC filter to settle after a new column is selected.

Why an active-high '238 instead of the more commonly useful active-low '138? Because the Schmitt-trigger inverters have asymmetric input thresholds that are roughly TTL compatible (yes, even in the 74HC family), so pulling a row-line down through a keyswitch and diode makes the RC filter harder to design. Pulling it up through the keyswitch & diode, and down through a resistor, is much easier to design for. Another design constraint is on the total current that all six row lines can draw on the single selected column if all six keys are pressed - I was able to make this less than 1mA. Mind you, another way of avoiding this problem would have been to insert the RC filter between two Schmitt-trigger inverter stages, but I like having been able to do it this way, and thus ballast the long lines across the PCB.

I could fit an individual diode beside each individual keyswitch, but it turns out that as well as resistor packs for bus termination etc, you can get diode packs. A relevant part number is 74S1053, which appears to hail from the days of bipolar logic, but TI still makes them! I even get to choose whether I want common-anode or common-cathode in the same part, and I just have to make sure the unused common terminals are tied off to whichever power rail keeps them reverse-biased. They cost more than individual diodes, but will save a lot of assembly time and mistakes.

This leaves a 7-bit scancode which is simply an input to the keymatrix, while the detected state of the selected keyswitch appears at the (complementary) output of the '151. The scancode is produced by the high-order bits of a free-running 12-bit counter (74HC4040) which is itself clocked by an oscillator sourced from the main CPU board. (Not necessarily Phi2, could be independent or simply come from a different stage of a frequency divider. If I plugged this into the 6502 Fake Finder, it would be a 1.8MHz clock intended for a UART, while the CPU itself runs at 460kHz.) For design purposes I'm assuming this clock is 8MHz, which results in a complete scan time of around 0.5ms, a column scan rate of just under 32kHz, and a key scan rate of 250kHz; the system should still work properly at slower clocks, but going significantly faster would run into the RC time constant on the row filters, which has to reliably flip a Schmitt trigger (in either direction) in about two key scan times.

Incidentally, 96 keys are sufficient to directly encode every ASCII character, ignoring control keys such as Return and Tab. Most keyboards combine two characters on each key, eg. upper and lower case, or a numeral and punctuation.

The debounce strategy is to treat any detected closed keyswitch as an immediate key-down event, unless the key was already considered pressed. The RC filters on each row give enough confidence in signal integrity to trigger key-down on that basis, even before the switch has stopped bouncing on make, and this minimises what is probably the easiest form of latency to measure or notice. Open keyswitches are debounced by requiring them to remain open for a configurable number of complete scan cycles before a key-up event is generated. Cherry MX is specified to finish bouncing within 5ms, which is ten scan cycles; some other types of switch are worse, and would thus require more bits to represent appropriate debounce timeouts.

To implement the key-up debouncing and filtering out of multiple key-down events for the same keypress, the scancode also indexes into an SRAM chip. I looked into many different permutations of memory technology to find out what the cheapest and simplest way to store 96 words of just a few bits each was - and it turns out that an ordinary 55ns 8Kx8b SRAM is it. Complete overkill, technically, but it will do the job. This forms the core of a two-phase state machine, such that the first phase loads the current value from RAM into a register (attached to which is a decrementer), and the second phase implements the following behaviour:
Code:
RAM state | RAM counter | Decremented | Keyswitch | New RAM   | FIFO load
----------+-------------+-------------+-----------+-----------+----------
Released  | Zero        |             | Released  | Zero      | No
Released  | Non-Zero    | Non-Zero    | Released  | Decrement | No
Released  | Non-Zero    | Zero        | Released  | Decrement | Key-Up
Pressed   |             |             | Released  | Load Reg  | No
Pressed   |             |             | Pressed   | Pressed   | No
Released  | Non-Zero    |             | Pressed   | Pressed   | No
Released  | Zero        |             | Pressed   | Pressed   | Key-Down
(Blank fields mean "don't care".) Using one bit of the eight to store a "was pressed" flag leaves seven to implement the counter, enough for up to 63.5ms of debounce delay on key-up. Much slower than that would potentially leave the user able to physically restrike the key within the debounce timeout, which would leave the computer blind to the fact it had been released at all!

One shortcoming of the above design is that the CPU can't directly query the keymatrix to discover whether a particular key is held down. But the CPU will maintain a bitmap of pressed keys which it can query, and as noted above, if that bitmap is corrupted there is a procedure to regenerate it reliably. The system reset will also cause keys held down during boot to be presented as key-down events, as long as the system reset is itself longer than the debounce delay.

It is technically possible for the FIFO to fill up, if the CPU doesn't service it faster than key events arrive. Since in that case it just ignores new data loads, I think I can just ignore the possibility. It just means it's possible for key-up events to arrive for keys that the CPU thinks weren't pressed in the first place, which is almost certainly harmless, or for key-up events to be missed for keys that were actually pressed - which will be obvious from system behaviour (if typematic repeats are implemented), and easily corrected by the user by pressing that key again.

And there is scope to extend the design beyond a mere keymatrix, due to the two rows of unused scancodes. These could be used to implement scroll wheels, depositing their events into the same FIFO as the keyboard. That's left to future work…


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 27, 2019 4:13 pm 
Offline
User avatar

Joined: Fri Nov 09, 2012 5:54 pm
Posts: 1431
I'm impressed by Don Lancester's ASCII keyboard:

Popular Electronics, April 1974.

On page 28, there is a schematic for an ASCII keyboard with 48 keys.
The ASCII code is generated by hardware.
Two MC789 chips, 4 transistors, 20 diodes, 18 resistors and a capacitor, would be hard to beat this.

MC789 is old Motorola RTL from 1966 or such,
to me the MC789 somehow looks like a 7405 with integrated pullup resistors to VCC (different pinout).

;---

But adding the features you had listed above would bloat this design pretty much.


Top
 Profile  
Reply with quote  
PostPosted: Tue Aug 27, 2019 4:53 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
An interesting solution for its time, but it lacks most of the desirable features I listed in an early paragraph. I see no debouncing (so the CPU would have to do that), and no capability of handling two keys pressed at once (with the specific exceptions of Shift and Ctrl, which are used to modify the code produced). If you *did* press two keys at once, you'd get some corrupted output code.

The use of bipolar transistor and diode logic probably also pushes up the power consumption - just look at all those bias resistors. Press any key to consume at least 10mW, and I'm not sure how to estimate what it uses statically. Again, acceptable at a time when CMOS logic was rare and special, but today we can easily do better.

The one advantage it does have is producing ASCII directly, saving a lookup table in the CPU, at the expense of a decidedly convoluted PCB design if the keys are laid out conventionally. The other sensible option would be to organise the scancodes by physical location, which the BBC Micro approximately does manage. (The typical PC keyboard does neither of these things consistently.)

Today the keyswitches themselves are the expensive part of the device, hence my decision to make the controlling logic smart and featureful without worrying too much about minimising its part count. Putting a scancode-to-ASCII lookup table in the computer is not nearly as difficult now as it used to be, but it would also be somewhat easier to lay out the matrix on the PCB to simplify the job, given the relatively inexpensive 4-layer manufacturing processes now available. Note, however, that one of my projects (which I haven't mentioned for a while) is a desk calculator, so most of the keys would not produce ASCII anyway.


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 28, 2019 6:01 am 
Offline
User avatar

Joined: Fri Nov 09, 2012 5:54 pm
Posts: 1431
The other end of the ladder would be the book:
PC Keyboard design, Annabooks, Gary Konzak, 1993,
ISBN10 0929392124, ISBN13 9780929392127.
//Listprice 224.30€, currently unavailable.

Considering your list of features, nailing all of them directly into hardware would give you some gray hairs.

IMHO your best bet would be imitating the Amiga, means to either integrate a minimal 6502 system into your keyboard,
or a W65C134 microcotroller.

Could be done with PIC or 8031 too, but since everybody does this, it would be plain boring. :)

An alternative to those exotic\expensive TI diode arrays might be BAT54ADW, BAT54CDW.
//6 pin SMD package containing 4 diodes.

BTW: there are keys with integrated decoupling diode, but they seem to be very exotic and hard to get:
MX1A-E1DN\MX1A-E1DW (Cherry), MX1A-11DN (ZF Electronics).


Top
 Profile  
Reply with quote  
PostPosted: Wed Aug 28, 2019 10:10 am 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Bear in mind that, before posting the above, I had already sketched out much of the design - including the RC filters - in KiCad. The only part I haven't yet implemented is the state machine described in the table; if all else fails, I'm pretty sure it's within the capabilities of a 22V10. Those devices are simple enough to build a fuse table and programmer by hand if need be.

Quote:
An alternative to those exotic\expensive TI diode arrays might be BAT54ADW, BAT54CDW.

"Non-stocked, call for quote." I assume that means I have to wait a month *and* pay through the nose. No thanks.

Of the alternatives that *are* stocked by Mouser, the TI chips appear to be the cheapest multi-packs when quantity is considered, costing less than €20 for the six I need for a 96-key matrix. Single diodes can be obtained for €10.40 per hundred, but the assembly of such devices would be correspondingly more tedious and error-prone. I'm willing to pay €10 to save the time and aggravation.


Top
 Profile  
Reply with quote  
PostPosted: Thu Aug 29, 2019 11:30 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Progress has been made, sufficient to complete the logic design and lay out the first version of a PCB.

I'm putting the controller logic and the keymatrix itself on separate PCBs, since the set of things that can go wrong with them is basically disjoint. This also allows stacking the keyboard proper on top of its controller to save space. This first version of the controller PCB is about 7x3 inches, making it a little smaller than the 6502 Fake Finder board, but still probably too large to squeeze into, say, a Model M chassis. But that's the price of doing everything in discrete logic and only through-hole components.

Pictures later. I need food and sleep now.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 30, 2019 7:17 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Well, I've spotted a timing problem that I need to fix.

In the current logic, the decision of whether to generate a key-down or key-up event is latched in a flipflop (to avoid glitching at the FIFO's input strobe) at the end of the first phase of each key scan. The decision of whether to send the output of the debounce decrementer latch (which stops counting with the "key up" flag value in the MSB when it expires) or that of the debounce *configuration* latch (which has that flag hardwired to "key down"), however, is effectively at the end of the *second* phase. It is possible for a keypress to occur during that window, and in fact it *will* occur by chance about every 256 keypresses. In that case, the key could be recorded in RAM as having been pressed, without actually generating a key-down event, and that record would suppress key-down events on subsequent scans.

The practical effect will be to drop a key-down event about every 3-4 lines of text, assuming an 80-column screen. Not exactly conducive to a high-quality typing experience.

So I need to fix it somehow, by ensuring that the decision of whether the key *is* down or not is consistent for both phases. But I have no spare gates or latches, so I'll either need to reconfigure an existing one or add another chip to the board, and the layout is already fairly dense. There's a reasonable chance, however, that I generate the correct flag value somewhere in the existing logic, and can simply feed that back into the RAM instead of the current arrangement. Another option is to latch the key data directly at an appropriate time, and de-glitch the FIFO signal some other way to free up the flipflop.


Top
 Profile  
Reply with quote  
PostPosted: Fri Aug 30, 2019 11:03 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
Happily, I think I've fixed it without needing to add any more hardware, just moving some wires around. The output of the row selector is now latched directly at the *beginning* of the first phase of the key processing, and the FIFO is now conditionally triggered towards the end of the first phase, rather than the second.

However this now leads to a second timing problem, since at 8MHz input clock there is only 62.5ns for the critical data path for the key-up event trigger to get out of the RAM (55ns by itself), through a pair of 4-bit adders' full carry chain, and then through a pair of XOR gates before reaching the timing gate. This does not seem very safe with 74HC logic, even though there's a definite possibility for the RAM to be faster than specified in practice.

(Both phases are limited to the final input-clock cycle - so nominally 125ns - of each half of the key-scanning cycle. This means the RAM chip is only selected on a 1/16th duty cycle, which should be a minor power saving if nothing else. The 125ns first phase is definitely long enough to get the adders' result around to the decrementer latch, but the FIFO trigger needs both the pre- and post-decrement high-order bits simultaneously, which is only possible during the first phase. The FIFO input timing gate now incorporates the 8MHz clock itself to select the second half of that phase.)

So I think I will need to adjust the RAM-related timing signals to double the duty cycle on the RAM, and thus loosen the timings enough to make the FIFO trigger reliable - ie. the timing gate only opens while the decision signal is stable. I may even be able to switch the two gates involved in that from 4-input to 3-input NANDs, giving me a spare gate for some future tweak.


Top
 Profile  
Reply with quote  
PostPosted: Sat Aug 31, 2019 9:50 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
With these fixes in place, may I humbly present the v1.01 design… which will certainly not be the final revision.

Currently the board has no provisions for mounting securely, and the routing isn't as neat or efficient as I would like, especially for the random logic. I may well find that, after the fixes, some of the smaller chips would do better in different places. And equally I may still find problems in the design, whether by inspection, simulation, or prototyping. But I'm happy enough to work on something else for a bit.


Attachments:
discrete_keyboard_101_front.png
discrete_keyboard_101_front.png [ 1.47 MiB | Viewed 2312 times ]
discrete_keyboard.png
discrete_keyboard.png [ 248.18 KiB | Viewed 2312 times ]
Top
 Profile  
Reply with quote  
PostPosted: Sun Sep 01, 2019 7:44 pm 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
(Very unusual chip orientations...!) [superficial comment, I know. Good to see the design come together. There's something of a message here, I think, in choosing whether to have nice hardware behaviour or to deal with things in software.]


Top
 Profile  
Reply with quote  
PostPosted: Sun Sep 01, 2019 8:13 pm 
Offline
User avatar

Joined: Sun Jun 30, 2013 10:26 pm
Posts: 1950
Location: Sacramento, CA, USA
BigEd wrote:
(Very unusual chip orientations...!)

I applaud the use of "creative" chip orientations, especially 45° and 180°, if they provide for more efficient routing and/or better density (which isn't immediately obvious to me here, but probably safe to assume). The only obvious trick you avoided was placing a chip on the backside of the board. Nicely done!

_________________
Got a kilobyte lying fallow in your 65xx's memory map? Sprinkle some VTL02C on it and see how it grows on you!

Mike B. (about me) (learning how to github)


Top
 Profile  
Reply with quote  
PostPosted: Sun Sep 01, 2019 10:28 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
The most natural position for the two 4-bit adders is actually perpendicular to and either side of the registers they operate on. I think I was trying to approximate that while minimising the width of the board, but the advantage in the latter may be minimal in this case.

Using the reverse side of the board is of course an option, but one with dubious benefit with through-hole components, where the chief problem is already threading traces between pins on their way to somewhere else. Downsides include the increased likelihood of making layout and/or assembly mistakes, due to the mirror image effect, and there may also be effects on safely mounting the board in a completed device (eg. it may be shorter but thicker).

I haven't yet exhausted the trace/space limits permitted by JLCPCB, though; the thinnest traces used on that board are 7-mil. In a later experiment I may try squeezing two 3.5-mil traces between a pair of pads, and see if that gains me anything. The traces leading to the keymatrix connector are deliberately much thicker because there are analogue effects (that RC filter is supposed to get rid of anything from 1 MHz upwards that might be coupled in, but still has to reliably charge and discharge within 10µs) though theoretically the column selectors will carry more current than the row lines at any given instant. There may be smaller sizes of resistor I can sensibly use.

Another trick I haven't yet tried is swapping gate inputs, or units of the same gate on one chip, for the sake of convenient routing (as opposed to convenient schematic drawing). It's not immediately clear whether KiCad's ERC is smart enough to recognise such equivalences by itself - probably not.


Top
 Profile  
Reply with quote  
PostPosted: Tue Sep 03, 2019 5:28 am 
Offline
User avatar

Joined: Fri Nov 09, 2012 5:54 pm
Posts: 1431
Nice going...
A custom TTL CPU would have a similar amount of chips.


Top
 Profile  
Reply with quote  
PostPosted: Tue Sep 03, 2019 6:04 am 
Offline
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10986
Location: England
Not wanting to detract at all from the wish to build a TTL keyboard, but it feels notable that the Amiga has a 6502 to run the keyboard - it might not even be a bad thought to use a 6502 to run the keyboard for a 6502 computer, in much the same way that some Z80 machines used a Z80 to run the disk.

I would be interested to know whether the idea to filter out high frequency interference is based on caution or on experience. Does it make any practical difference if you omit that filter?

I've thought about debouncing from time to time. It's a good idea to minimise latency - many approaches to filtering bounces will add latency. My thoughts have led me to think of approaches which are sensitive only to the initial transient. If the switch is open, then the first close is enough to signal closing, but there must then be a lockout (10ms? 100ms?) during which openings are not sensed. And then, after the lockout, the very first opening transient should signal opening, but again with a lockout.


Top
 Profile  
Reply with quote  
PostPosted: Tue Sep 03, 2019 12:49 pm 
Offline

Joined: Mon May 21, 2018 8:09 pm
Posts: 1462
I basically read Jack Ganssle's guide to switch debouncing and extrapolated from there. He has some fun graphs of how keyswitches behave in the analogue domain; often, what *looks* like contact bouncing is actually TTL gate chatter from an invalid logic level during the transition - but equally, *real* bounces can occur with significant gaps in the signal.

Some notable statistics on maximum switch settling time:

- Cherry MX specifies maximum 5ms, usually achieves much less, at least with a reasonably new switch. Most other reputable keyswitches are similar in this respect.
- Grayhill specifies maximum 10ms.
- Someone measured a buckling-spring keyboard's worth of switches at about 3.25ms, which to me justifies taking 5-10ms as a reasonable maximum for the type.
- The otherwise-rare Futaba "simplified linear" switches used in the BBC Micro specified 1ms settling, which is exceptionally good. (The BBC Master used an inferior type with 10ms maximum settling and also much worse reliable lifetime, then changed to membrane.)
- Some unspecified customer of Ganssle's encountered a bargain-basement Chinese keyswitch that exhibited 200ms typical settling for both make and break, which is exceptionally bad.

All of the above (except the el-cheapo Chinese monstrosity) are covered by my configurable design, with some margin, since I can set the debounce timeout as high as 63ms - the latter being comparable to many commercial PC keyboards' latency. For comparison at 60Hz screen refresh, each refresh takes 16.7ms. Being able to keep the maximum input latency to less than a video frame, with the normal types of keyswitch, is already an improvement over most PC keyboards.

One influence on my design is that I consider key-down latency much more important than key-up. In most typing situations, there is no direct feedback when the key releases; it merely becomes available for the next keypress. In gaming, releasing the key accurately can be important for halting movement or stopping a burst of fire, but it's still harder to perceive the connection than for key-down actions. The same goes for typematic repeating. If key-up latency did prove to be just as important as key-down, then the "edge and lockout" strategy would make sense, but I'd have to consider whether that would further complicate the logic.

The RC filters effectively implement a 5-microsecond debounce filter on the keymatrix - you can see they're labelled "EMI filter" on the PCB - and the Schmitt trigger gates effectively eliminate analogue effects due to contact wiping. You could undoubtedly build a simplified controller that focused on that end of the board, requiring somewhat more software intervention than my design, which would still perform well. But considering the overall BOM, it might not be all that much cheaper. Purely for the sake of illustration, I might actually do that - the scan code would look something like:
Code:
KBD_Interrupt:
 Take keyboard out of auto-scan/interrupt mode.
 Call manual scan routine.
 RTI

Timer_Interrupt:
 If keyboard scan due, call manual scan routine.
 (etc.)
 RTI

KBD_Scan:
 For columns 0 to 15:
  Select column
  Wait 64 cycles
  Read row bits (keys apparently pressed in current column)
  If row bits differ from currently known pressed keys:
   Perform debounce
   Update known pressed keys
   Generate key events
 If no keys were pressed and debounce timers are all quiescent:
  Put keyboard in auto-scan/interrupt mode.
 RTS
A quick look at the BBC Micro's keyboard handling code shows that this can get a bit messy. I think the BBC Micro doesn't even try to handle key rollover; it just focuses on a single keypress until it ends.


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 29 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 48 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: