============================================================== == Hardware specifications for the Wi-Fi Detector == == http://www.getdigital.de/products/Wifi_Finder_LCD == == == == (c) 2007 Michael Buesch == == == == This hardware specification file is licensed under the == == Creative Commons Attribution Share Alike license == == http://creativecommons.org/licenses/by-sa/3.0/ == ============================================================== ==================================== === General hardware information === ==================================== The microcontroller is an Atmel Mega168 with an external 12Mhz clock. The device has a standard Atmel ISP (In System Programmer) connector on the PCB (printed circuitry board). (The 6 solder pads on the lower right). The pin layout is the standard Atmel layout, but I'll draw it here for reference: ^ . AVR controller PCB . lower right edge | ------------- | | MISO | VTG | | |-------------| | | SCK | MOSI | | |-------------| | | RST | GND | | ------------- | <...------------------------------------------ ============= === PORTS === ============= Data directions: DDRB: 0b00000000 (all input) DDRC: 0b11111111 (all output) DDRD: 0b11011100 Port bit usages: PortB: --------------------------------- bit # | DDR | Init | Description --------------------------------- bit 0 | in | 1 | Key (next) bit 1 | in | 1 | Key (back) bit 2 | in | 1 | Key (scan/lock) bit 3 | in | 0 | ? bit 4 | in | 0 | ? bit 5 | in | 0 | ZD1211 LED0 (array pin 4) bit 6 | in | 0 | ? bit 7 | in | 0 | ? PortC: --------------------------------- bit # | DDR | Init | Description --------------------------------- bit 0 | out | 1 | LCD clock signal bit 1 | out | 1 | LCD data signal bit 2 | out | 1 | LCD register select; 0->command, 1->data bit 3 | out | 1 | LCD chip select; 0->selected, 1->inactive bit 4 | out | 1 | LCD reset; 0->reset, 1->operation bit 5 | out | 0 | N/C? bit 6 | out | 1 | N/C, AVR Reset pin bit 7 | out | 1 | N/C PortD: --------------------------------- bit # | DDR | Init | Description --------------------------------- bit 0 | in | 1 | USART RXD (array pin 8) bit 1 | in | 0 | USART TXD (array pin 5) bit 2 | out | 0 | ZD1211 power control bit 3 | out | 0 | Battery measure enable bit 4 | out | 1 | LCD backlight 1->on, 0->off bit 5 | in | 1 | ZD1211 LED1 (array pin 3) bit 6 | out | 0 | ? bit 7 | out | 1 | ? N/C -> not connected For Input pins "Init" means 1->pullup_enable, 0->pullup_disable =========== === LCD === =========== The LCD has 96 pixel-columns with 8 pixels each and 4 lines. The LCD is addressed as row and column, where each 8 pixel column is represented by one data byte (8 bit). Column 0 1 2 3 4 5 6 7 8 9 ... 95 ---------------------------- | * * * * * * * * * * ...... | | * * * * * * * * * * ...... | | * * * * * * * * * * ...... | row 0 | * * * * * * * * * * ...... | | * * * * * * * * * * ...... | | * * * * * * * * * * ...... | | * * * * * * * * * * ...... | | * * * * * * * * * * ...... | -------| | | * * * * * * * * * * ...... | row 1 | * * * * * * * * * * ...... | . | . . . . . . . . . . ...... | . | . . . . . . . . . . ...... | row 3 | . . . . . . . . . . ...... | ---------------------- The * are the pixels. Dots (.) are continuations. Commands: 0x04 => ? Used when writing data 0x12 => ? Used when writing data 0xAF => Enable the LCD? 0xB0 + line # (0-3) => move cursor to line Sending a command byte: * Drive LCD Register Select low * Do the "Generic byte send algorithm" Sending data byte: * Drive LCD Register Select high * Do the "Generic byte send algorithm" Generic byte send algorithm: * Init Clock and Data signals to high * Drive LCD chipselect low * For each bit to send do (from MSB to LSB) * If the bit is set * Drive the LCD Data line high * else * Drive the LCD Data line low * Drive the LCD Clock line low * Drive the LCD Clock line high * Wait 1 uSec * Drive the LCD Clock line low * Drive LCD chipselect high Sending character data to the LCD: * For each line (0-3) * Move the cursor to the desired line (command 0xB0) * Send command 0x12 * Send command 0x04 * For each data byte of the line * Do the "Sending data byte" algorithm. A byte is one pixel column in the selected line. The LCD will automatically jump to the next column Initialization: * Drive "LCD reset" low for 100ms. * Drive reset high and wait another 50ms for the device to init itself. * Drive chipselect high and init the other lines. * Send command 0xE2 * Send command 0xAB * Send command 0xC8 * Send command 0x40 * Move the cursor to line 0 * Send command 0x10 * Send command 0x00 * Send command 0xA1 * Send command 0xA6 * Send command 0xA2 * Send command 0x2F * Send command 0x24 * Send command 0x81 * Send command 0x00 * Clear the display (write all-zero data) * Send command 0xAF ======================================== === Check if we are connected to USB === ======================================== A check if we are connected with the ZD1211 board's USB connector to a computer can be done though the USART TX pin. First make sure that the USART is disabled, so we can use the USART TX pin as a normal input pin (PinD bit 1). If the pin (PinD bit 1) is driven HIGH, we are connected to USB. Checking whether USB is connected can also be done through ADC7. See the ADC7 description below. ======================= === ADC measurement === ======================= * Write the ADC configuration values to the ADC control registers. This includes selecting the reference and MUX settings. * Trigger 4 ADC measurements by doing this 4 times: * Start an ADC conversion, wait for it to finish and read the ADC value. * Get the average of the 4 measurements. That is the measurement result. ===================================== === Measuring the battery voltage === ===================================== Measuring the battery voltage is done through ADC7. ADC7 settings: * Reference: 1.1V internal * ADC Prescaler: 16 * No autotrigger * Left Adjust Result bit is not set Measuring the voltage: * Drive "Battery measure enable" of PortD high. This enables the external measuring circuitry. * Wait 10 uSec for the circuitry to stabilize. * Do an "ADC measurement" (see above) on ADC7 * Drive "Battery measure enable" of PortD low. This disables the external measuring circuitry. Disabling is important to avoid drawing unnecessary current. * Interpret the result of the measurement by looking up the battery voltage table. Battery measurement key figures: (A more exact ADC-value to battery-voltage lookup table can be generated by the battery_tab_gen.py script) ------------------------------------------------------------ ADC7 value | Description ------------------------------------------------------------ 0x0FC | Absolute minimum battery voltage 1*) >= 0x124 | Battery voltage is low >= 0x130 | Battery voltage is medium >= 0x13C | Battery is fully charged -----------+------------------------------------------------- >= 0x171 | We are not running on battery. | Power is supplied through the USB port. 1*) --- WARNING --- When minimum battery voltage is reached turn off everything including all IRQs and put the microcontroller into sleep. We must avoid draining battery voltage below 3.0V, as that physically destroys the battery. Note that the lower the battery voltage is, the less wireless networks the device is able to find. ============================== === Recharging the battery === ============================== The battery will automatically get recharged while we are connected to USB and have the power switch turned ON. The device will automatically stop charging when the battery is fully charged. Checking the charge status is done by measuring ADC6 while being connected to USB. Note that the "Battery measure enable" must NOT be pulled high while measuring ADC6. --------------------------------------------------------------------------- ADC6 value | Description --------------------------------------------------------------------------- 0x0 <= ADC6 <= 0xC0 | Not charging battery (Switch not in ON state) 0xC1 <= ADC6 <= 0x160 | Charging battery (Switch is in ON state) 0x161 <= ADC6 | Battery is fully charged (Switch is in ON state) ================================= === Accessing the ZD1211 chip === ================================= The zd1211 chip is accessed through the USART interface. USART settings: * Asynchronous * 115200 baud (UBRR = 0x000C, at 12Mhz crystal with U2X speed doubler) * 8 data bits * 1 stop bit * No parity Scanning for wireless networks: * To apply power to the ZD MAC and RF chips, pull PortD bit 2 high. It will immediately start scanning after power is applied. The device will draw about 200mA at 3.7V when enabled. * The original firmware writes 0xEE through the UART now, though that seems bogus. Not sure why they do that. * Wait for ZD1211 to finish the scan: Poll the UART in a loop until a 0xAA byte is read. Consider using a timeout. * Loop * Read 127 bytes from the UART and handle them (see "Received data" below). * Try to read the next byte from the UART. * If the UART was empty and no byte was read, break the loop. * If the byte is not 0xAA an error occurred. * Disable power on the ZD1211 by pulling PortD bit 2 low. Received data: Each received data chunk is 127 bytes long. It consists of a small header and a stripped down IEEE 802.11 beacon or probe response. The header is 3 bytes long: ----------------------------------------------------------------- | byte 0 | Unknown, seems it can only be 0x00 or 0x01. | |---------------------------------------------------------------| | byte 1 | The channel number this beacon was received on | |---------------------------------------------------------------| | byte 2 | The RX Signal Strength Indicator | ----------------------------------------------------------------- | 124 bytes of beacon data follow. The IEEE 802.11 header | | of the beacon is half-stripped. So this data block starts | | with the last byte of the SA mac address. (So the second | | byte of this block is the first byte of the BSSID). | ----------------------------------------------------------------- Note that the only reason for including the last byte of the SA in front of the BSSID is alignment. It will align the beacon packet to a 4byte boundary. Though, that doesn't matter for us on the 8bit controller, of course. See the IEEE 802.11 specifications for more info on the IEEE 802.11 wireless header data (which is partially included in the data) and the IEEE 802.11 beacon and probe response packets.