Nokia N85 / N86 AMOLED interfacing (& surprise) …
Notice that it is an AMDN001 marked module (which is, in fact, real AMOLED from N85/86).
Now the surprise : it works with the command set known from E51/6500c LCDs…
Yes! No changes, just solder the wires, build +5V/-5V DC-DC converter & Voilla…
The DC-DC can looks like : (I’ve managed to homemade it on 2.5×3.0cm single sided PCB).
n86_tps65136_sch
TPS65136 is available in QFN package only, its tricky to solder it at home, but having any hot-air & flux should do the trick. Remember that thermal pad should be GND-ed (& soldered too, of course).
UPDATE #1: There is one error in schematic – the L1 inductor should be 2.2uH or 4.7uH instead of 10mH (ekhm… “hardly available” 🙂 ).
To successfully drive this AMOLED it is sufficient to have such wiring : D0-D7, RES, WR, DC for control, and power sources : 3V3, ELVDD, ELVSS.
There is no need for 1V8 and level shifters like LVC4245. Driving VIO pin (12) with 3.3V voltage we’re getting whole interface bus working at 3.3V. (Don’t know exact timing impact with such voltage change, but it works at full speed achievable with PIC32MX parallel master port)
Nokia Display Modules Hacking Platform :)
NDMHP in short 🙂 easy, huh ?
Today, I’ve got some hardware & software to share – In the meantime I’ve created some nice piece of hardware, and I named it as you can see above.
It consists of :
1). PIC32MX340F512H prototype board (PIC & necessary components to run it)
2). Voltage-level shifter based on LVC4245
3). Adapter board with voltage inverter & stabilizer (~+5V/-5V for amoled display) – not recommended to use, try to get TPS65136 (www.ti.com/product/tps65136) instead.
4). Power source with different voltages (1.8V, 2.5V, 3.3V, 5.0V, 12.0V)
Here comes some pictures of this crap :
Fig.1. PIC32MX proto-board
Fig.2. Level-shifter & n86 adapter board with DC-DC inverter & stabilizer
Fig.3. Photo of working AMDF001 connected to that crap above.
Here comes some schematics :
1) I would not provide you with proto-board of PIC32MX, because it is so self understandable, that it would be a shame to do this…
2) Level-shifter & n86 adapter board :
level_shifter_sch
n86_oled_adapter_sch
And some code, (very dirty but working…) :
https://rapidshare.com/files/2973078098/hack_n86_amoled.zip
Some description :
PC is connected to PIC32 via RS232 @ 57600 bauds (MAX3232 not visible – mounted inside COM1 plug, powered from PIC32 proto-board). PC is running C# program – win_amo_hack, PIC32 is flashed with included code (n86_amoled_hack).
Communication protocol PCPIC is described below :
– commands are sent as text strings
– commands :
a) ‘r’ – reset (assert RESX line low for 5ms & release high)
b) ‘C’ – pull chip select low (CSX=LOW)
c) ‘c’ – release chip select high (CSX=HIGH)
d) ‘i[xx]’ – write index register/execute command simple command (DCX=LOW, perform write of hexadecimal number [xx] via ParallelMasterPort, eg. “i29” – send DISP_ON command on MP1.0 protocol
e) ‘d[xx]’ – write single byte of data (DCX=HIGH, perform write of hex [xx] via PMP, eg. “d00” – send 0x00 to LCD)
f) ‘t’ – return tearing line status (returns t00 or t01 according to TE line level)
g) ‘g’ – read register or data (DCX=HIGH & perform read via PMP)
Examples:
“i01i11i29” – this string will initialize MP1.0 display (reset, sleep-out, display-on)
“i2cd00d11d22” – this string will send one pixel data (0x2c – GRAM_WRITE), color 0x001122
Win_amo_hack has also ability of execution of Lua scripts.
It defines two functions : amoSend & amoTear. First one takes single string argument & sends that string to PIC32. Second one returns TE line status as a byte.
Sample Lua script :
amoSend("Ci2ad00d00d00defc")
amoSend("Ci2bd00d00d01d3fc")
amoSend("Ci2c")
for y=0,319 do
for x=0,239 do
amoSend(string.format("d%02xd%02xd%02xd%02xd%02xd%02xd%02xd%02xd%02xd%02xd%02xd%02x",x,x,x,x,x,x,x,x,x,x,x,x))
end
end
Well, that’s basically it.
This platform is quite powerfull and can be used to hack multiple types of LCDs, as long as LCD is interfacing via Intel-80 parallel bus.
Have fun.
Nokia N85/N86 AMOLED display hacking project AMDF001 / AMDN001
Well, after a while , I’ve found that E51-like LCD displays are barely readable in sunlight, which renders them unusable in outdoor conditions. So, after deep search, I’ve found nice and cheap potential solution : N85/N86 display.
It is active matrix OLED screen (AMOLED) 320×240, 2.58″, manufactured by (I believe) Samsung SMD (www.samsungsmd.com). There is markup on this OLED : AMDF001 AMDN001 (see below …) (which is probably FPCB model type (flexible printed circuit)). Other ID’s are : 4850084 (which is probably manufacturer ID code (see google)), MP1.0 which denotes interface protocol? (MeSSI ?)
Display have FPC 24-pin connector widely used by Nokia (same as E51), but different pinout is used – see N85/N86 schematic wiring diagram -> google it, download level 1/2 manuals.
Nokia uses codename Falcon for this display -> no effect after google.
What I’ve done :
1. As microcontroller I used PIC32MX (340F512H), communicating with PC via UART
2. I’ve created 2 prototype boards :
a) level shifter board (3.3V -> 1.8V) using 74LVC4245A (2x) one for databus D0..7, one for controls (RDX,WRX,RESX,DCX)
b) OLED display power supply (MC1727-500 & MAX889) generating -4.9V & +4.6V for ELVSS & ELVDD respectively.
3. I’ve dismounted 24 pin connector from display’s FPCB and soldered 24 wires to that connector’s pads (I’ve used old 80-pin ATA cable as a small wire donor)
After battle with my solder gun I finally ended up with working prototype, with NULL knowledge of protocol…
Digging the Web for similar display’s datasheets I’ve found that similar displays controllers using similar interface protocols, of course AMDF001 is using Intel 80 8-bit bus, just like E51 module.
It seems that it is using such protocol :
1. with DCX=0 write register addr (D0..7 => reg index)
2. with DCX=1 write data to that register … 8-bit or 16-bit??? (double 8bit transfers?)
After brute-forcing this module I’ve found that it is responding to commands (screen blinks, fades in/out, eventually even GRAM memory contents showed up on screen, nice)
Now it is long road to descramble the protocol & register locations…
Or maybe someone has something to say in this topic ???
Any help appreciated!
Update #1 : After days of digging the net searching for possible driver IC that drives this amoled, I’ve found that:
1) probably I have problem with connection bus (amoled seems to respond randomly to sent commands)
2) amoled is responding only when (sic!) LVC4245 is driven reversed (pic<-amoled) on data bus… strange..
3) I personnaly think that IC might be LD9014 from LDT,inc.
4) I really don't think it is S6E63D6X, just because of 262K color depth instead of proclaimed 16.7M for this amoled
Update #2 : Shame on me! These modules I got aren’t AMOLEDs… They turn out to be cheap chinese fakes – LCDs, looking like AMOLED, but they’re not.
Waiting for new delivery, hoping for getting real AMOLED now for n85/86.
Bloody differences ? Here you’ve got :
1) Shorted pins 11 & 12 (EL_ON VIO), gives constant 1.8V on EL_ON…
2) There is small BGA packaged IC on the FPCB just below the screen ( on the back side) – it is probably dc-dc charge pump for LED backlight (very smartly hid below the screen), original AMOLED has only some discrete smd parts on FPCB…
3) real AMOLED has MP2.1 protocol designation & AMS258DN01 module type (driver IC still unknown)
Update #3 : Module marked AMDF001A is an ordinary TFT module compatible with MP1.0 protocol, just like E51 module. Only pinout & backlight driving are different.
Still waiting for AMDN001 modules (which should be amoleds)
Project attempt: Pulseoximeter
Source :
http://www.oximeter.org/PulseOx/principles.htm
http://www.edaboard.com/attachments/24135d1178378436-cc2004-12_2018-pdf
http://www.edaboard.com/attachments/24304d1179237986-ti_app__notes_for_pulse_oximetry_1486-pdf
http://www.circuitcellar.com/microchip2007/winners/DE/abstracts/MT2278_Abstract.pdf
http://www.cypress.com/?rID=2696
Did some basic research…
Description of operation :
The device uses 2 LEDs, one bright red (about 640nm) and one IR (about 910nm). These LEDs transflects the finger (or other suitable tissue), and the light gets into sensor.
Sensor can be a photodiode (such as BPW34), or Light-to-Frequency converter (like TSL230…)
Because I cannot obtain TSLxxx (the easier solution), I’m forced to use photodiode BPW34.
Using TSLxxx leads to “almost” pure digital solution, simply introducing TSL’s output into InputCapture module of MCU, counting pulses, some digital filtering, AC part extraction & showing up results.
Photodiode is a bit trickier… Signal is very small, I have to use instrumentation amplifier with very low drift as an input opamp (transimpedance approach), filter DC part of the signal, extract the “pulse” wave, amplify it and then sample via ADC (then filtering, calculations & ->LCD).
There are many analog part solutions to this problem, but I didn’t find the one I could repeat.
(Cypress’ version is very sophisticated, but I cannot find any “cheap” PSoC chip near my localization, combining it with need for new programmers/debuggers rendering it very far from acceptable…)
Do you have any ideas, how to design analog part of this project ?
I2C EEPROM & PIC32
Few useful examples, how to force HW I2C module of PIC32MX to collaborate with I2C EEPROM chip, like Microchip’s 24LC1025.
I2C Module Initialization
void eepromInit(void) { I2CConfigure(EE_I2C, I2C_ENABLE_SLAVE_CLOCK_STRETCHING | I2C_ENABLE_HIGH_SPEED); I2CSetFrequency(EE_I2C, GetPeripheralClock(),400000); I2CEnable(EE_I2C, TRUE); }
For single master-slave enviroment, you can omit I2C_ENABLE_SLAVE_CLOCK_STRETCHING config word.
Reading from EEPROM.
void eepromRead(unsigned int ee_addr, unsigned char *buf, unsigned int len) { // Start StartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 0); // Write control byte IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr >> 8); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? RestartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 1); // Read command IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? while (len) { I2C2CONbits.RCEN = 1; while(!DataRdyI2C2()); *buf = I2C2RCV; buf++; len--; if (len) { // ACK the slave I2C2CONbits.ACKDT = 0; I2C2CONbits.ACKEN = 1; } else { // NACK the slave I2C2CONbits.ACKDT = 1; I2C2CONbits.ACKEN = 1; } while(I2C2CONbits.ACKEN == 1); /* Wait till ACK/NACK sequence is over */ } StopI2C2(); IdleI2C2(); }
where EE_ADDR is #defined as 0xA0 , corresponding to EEPROM’s control word.
This function has limited functionality – it can only read first 0xFFFF bytes of data from EEPROM – no code provided to set B0 bit in config word (see datasheet).
Writing to EEPROM.
void eepromWritePage(unsigned int ee_addr, unsigned char *buf, unsigned int len) { // Start StartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 0); // Write control byte IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr >> 8); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? MasterWriteI2C2(ee_addr); // Address of operation IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? while (len) { MasterWriteI2C2(*buf++); IdleI2C2(); if (I2C2STATbits.ACKSTAT) return; // NACK'ed by slave ? len--; } StopI2C2(); IdleI2C2(); // Do acknowledge poll (indicating, that eeprom has completed flashing our bytes while(1) { StartI2C2(); IdleI2C2(); MasterWriteI2C2(EE_ADDR | 0); // Call the eeprom IdleI2C2(); if (I2C2STATbits.ACKSTAT==0) break; StopI2C2(); IdleI2C2(); } StopI2C2(); IdleI2C2(); } void eepromWrite(unsigned int ee_addr, unsigned char *buf, unsigned int len) { int bytes_to_write; while (len) { bytes_to_write = 0x80; // default xx1025 pagesize if (len<bytes_to_write) bytes_to_write = len; eepromWritePage(ee_addr, buf, bytes_to_write); len-=bytes_to_write; buf+=bytes_to_write; ee_addr+=bytes_to_write; } }
because of limited amount of data for single write command (page size of this eeprom is 128 bytes), you should call eepromWrite(…) function, which can handle writes in 0x0000-0xffff addresses in eeprom space. (the same limitation with B0 bit as for eepromRead() func).
Have fun.
RFM22 PIC32MX library and code example
Here you go with the library :
RFM22.ZIP
Consider it as a very young release, highly uncommented and not optimized.
It works with PIC32MX MCUs. SPI is currently emulated in software, because for unknown reason, the HW code doesn’t work.
To use library, you should #include "rfm22.h"
in your code, and add rfm22.c
to your project.
You should also look at the beginning of rfm22.h.
#ifdef __PIC32MX #define RFM22_nIRQ _RD9 #define RFM22_nRES _LATB4 #define RFM22_nSEL _LATG9 #define RFM22_SCK _LATG6 #define RFM22_SDO _LATG8 #define RFM22_SDI _RG7 #define RFM22_nIRQ_TRIS _TRISD9 #define RFM22_nRES_TRIS _TRISB4 #define RFM22_nSEL_TRIS _TRISG9 #define RFM22_SCK_TRIS _TRISG6 #define RFM22_SDO_TRIS _TRISG8 #define RFM22_SDI_TRIS _TRISG7 // external interrupt with nIRQ line hooked #define RFM22_int_ie IEC0bits.INT2IE #define RFM22_int_flag IFS0bits.INT2IF #endif // define below to use SW emulated SPI #define USE_SW_SPI
You should tune it to your hardware routing.
It is nice to wait for some time after power-up of your MCU, so after stabilizing your device you should initialize RFM22 :
void init_system() { // disable JTAG port DDPCONbits.JTAGEN = 0; // config wait-states & cache SYSTEMConfig(GetSystemClock(), SYS_CFG_WAIT_STATES | SYS_CFG_PCACHE); } int main() { DelayUs(100000); init_system(); AD1PCFG = 0xffff; init_radio(); // Turn on the interrupts INTEnableSystemMultiVectoredInt(); ...
where init_radio() is defined with :
void init_radio() { // FIRST! enable INT2 INTCONbits.INT2EP = 0; // INT2 edge -> int request at FALLING IPC2bits.INT2IP = 2; IPC2bits.INT2IS = 3; IFS0bits.INT2IF = 0; // clear flag IEC0bits.INT2IE = 0; // enable int | CURRENTLY DISABLED in LIBRARY !!! // THEN! initialize rfm22 !!! _TRISB5 = 1; _TRISD9 = 1; rfm22_Init(868, GetPeripheralClock(), 5000000); rfm22_go_rx(); }
_TRISB5 and _TRISD9 routes nIRQ signal in my project, you may ommit this lines.
GetPeripheralClock() is a macro defining PB_CLK of your PIC32 in [Hz]. 868 is a literal indicating working frequency of RFM22 module.
rfm22_Init(…) initializes SPI, performs SW_RESET of RFM22 and sends basic configuration of RFM22 registers.
rfm22_go_rx() switches RFM22 module into RX mode.
In your main loop you should poll nIRQ line status :
while(1) { if (!RFM22_nIRQ) rfm22_Handle_IRQ(); ...
There is nothing wrong with INT2 external interrupt attempt, but be aware of proper timings and interrupt service routine execution length. If your main loop is executed fast enough, there is no need to use an external interrupt handler, and your code would be level-related-IRQ rather than egde-related-IRQ using INT2.
For example, INT2 handler should looks like :
void __ISR(_EXTERNAL_2_VECTOR, ipl2) INT2Handler(void) { rfm22_Handle_IRQ(); IFS0bits.INT2IF = 0; }
Remember to set proper ipl in this ISR function invocation, according to defined interrupt priority level for INT2.
Currently, rfm22_Handle_IRQ() is defined with following code :
void rfm22_Handle_IRQ() { rfm22_ReadStatus(); // check POR condition if (rfm22.isr2.b.IPOR) { rfm22_go_ready(); } if (rfm22.state == RFM22_TX) { if (rfm22.isr1.b.IPKS) { // packet sent, RF module went back to READY rfm22.tx_state = RFM22_TX_COMPLETE; } } if (rfm22.state == RFM22_RX) { if (rfm22.isr1.b.IPKV) { // received valid packet // get the RX FIFO int i; int len = rfm22_Read(0x4B); // get the received packet length rfm22_StartBurst(0x7f,0); // read FIFO in burst read mode for (i=0;i<len;i++) { rfm_rx_buffer[i] = rfm22_BurstRead(); } rfm22_EndBurst(); rfm22.rx_state = RFM22_RX_COMPLETE; } if (rfm22.isr1.b.ICRC) { // CRC-error occured - restart receiving rfm22_ResetRxFifo(); rfm22_go_rx(); } if (rfm22.isr2.b.IPVD) { rfm22_last_rssi = rfm22_Read(0x26); // get RSSI } } }
I think it is understandable with a little effort.
Code asserts specific state machines according to RFM22 interrupts, e.g. sets RFM22_TX_COMPLETE state of library TX state machine, when packet sent interrupt flag was set.
User may poll for this state in main loop.
RFM22_RX_COMPLETE indicates that rfm_rx_buffer[] contains downloaded data from recently received packet. User should poll for this flag, and perform specific action, e.g. :
while (1) { ... if (rfm22.rx_state == RFM22_RX_COMPLETE) { // process incoming data rfm22.rx_state = RFM22_RX_IDLE; // indicate, that packet has been processed ackbuf[0] = 0xAC; ackbuf[1] = rfm22_last_rssi; // RSSI rfm22_tx_buf_block((uchar*)&ackbuf[0],2); rfm22_go_rx(); }
UPDATE 07.02.2011: Newer version of RFM22 lib is just uploaded and available under link at the top of this post. Same restrictions about using it : IT IS A DRAFT. IT WORKS… SOMETIMES… 🙂 There are many holes in the code and lacks of documentation, but I really don’t have time to clean up this mess. Maybe someday.
RFM22 Programming tutorial – PART #2
RFM22 internal registers
When you look into datasheets, you may feel a little bit lost 🙂
Yeah, there are near 127 registers in this little module, but many of them are set-and-forget ones.
Moreover, there are MSExcel spreadsheet calculators, providing you with set of calculated values for
your RFM22 module. You only have to enter desired transmittion parameters.
Look at : Calculator for Vx silicon revision
Calculator for A0 silicon revision
Calculator for B1 silicon revision
To determine your RFM22 chip’s silicon revision, read register at 0x01.
More important registers are (these you should become familiar with, these needs frequently changes during operation):
Notes: Normally, there is a little need to read this register in FIFO Packet Handler mode. Frankly, I don’t pay attention to this register at all, using FIFO+PH.
0x03 – Interrupt flags register #1
0x04 – Interrupt flags register #2
These registers are quite good described in the datasheet, all flags are more or less self-explanatory.
Reading these registers clears indicated interrupt request and releases nIRQ line of RFM22.
You should read them after nIRQ goes LOW.
if (!nIRQ)
rfm22_Handle_IRQ();
0x05 – Interrupt enable register #1
0x06 – Interrupt enable register #2
When specific bit in these registers is SET, then asserting particular flag in 0x03/0x04 also drives nIRQ LOW.
You should set ONLY these interrupts enabled, you’re interested in during current mode of operation, e.g. you should enable PKTSENT interrupt before entering TX mode – when nIRQ goes LOW you would know that packet has been sent, and you don’t need to check all interrupt flags. That approach would simplify your code to maximum extent.
0x07 – Mode of operation register #1
This is the most important register of the module.
ipreaval – valid preamble detected – asserted during reception of valid preamble. THIS IS THE MOMENT when you should save RSSI variable (content of 0x26 register) – that would indicates signal strength of transmittion.
iswdet – synch word detected & match – module would assert this bit, when valid synch words are detected during reception of current packet, rather informative…
icrerror – CRC error – received packet is corrupted – CRC calculated & received don’t match. You should respond to this IRQ with restarting RX mode (reset RX FIFO & set RX mode ON).
ipkvalid – Valid packet received – this is the most wanted flag during reception – indicates that RX FIFO contains healthy data, just as you sent them on the TX side.
0x08 – Mode of operation register #2
This register controls mainly RX/TX FIFO buffers. Other settings are less important.
send(0x08,0x02); send(0x08,0x00);
0x72 – Frequency deviation / AFC limiter
Why this magic register is important? It depends on silicon revision of your RFM22 chip. When it is V2 (register 0x01 == 0x02) it has double function. In RX MODE it acts as Automatic Frequency Control Limiter – you should set this reg BEFORE entering RX MODE, according to calculated value. In TX MODE this register acts as Frequency Deviation register. You should write desired frequency deviation value BEFORE entering TX MODE.
RFM22/23 Programming tutorial – PART #1
Because there is a serious lack of information over the internet about programming RFM22 modules, here you’ve a quick tutorial.
Here you go with the connections :
Fig.1. Schematic of RFM22 connections
Description of Fig.1. :
I’m using PIC32MX MCU, but any should work. If your MCU is 5V powered, you must provide some level shifters on SPI lines, but nowadays I believe that it is easier to do the whole thing on 3V3 MCU & stuff than wasting mcu pins & time & pcb space with 74lvc4245…
Philosophy of operation
RFM22 may be used in many different modes. The one I would describe is FIFO mode with Packet Handling. It is the easiest mode to implement, RFM22 is doing the most of the job, MCU has hands free most of the time.
FIFO mode with Packet Handling means, that during transmition, MCU is uploading data into radio’s FIFO, RFM is encapsulating user’s data into packet structure and sends it over RF using correct timing, defined in setup step.
During reception, RFM is detecting preamble, synch words, packet headers (optional), receiving subsequent data bytes into Rx FIFO and doing CRC check over the packet contents (data only or whole packet). If CRC is OK, then RFM is asserting an interrupt request.
Packet structure of RFM22 :
[PREAMBLE][SYNCWORD][HEADER][PKTLEN][DATA 0…n][CRC]
Preamble consists of 1-512 bytes (user configurable count) of 0xAA (10101010b)
Synch word usually equates to 0x2DD4, but may be configured to desired values
Header consists of 0-4 bytes (user configurable count & content), consider it as a IP address of packet – receiving side may compare it with predefined variables to determine destination of received packet.
PktLen is 1 byte if variable packet lengths are in option, it may be ommitted when RFMs are configured to deal with fixed length packets.
CRC is checksum calculated over data or whole packet structure, usign one of four predefined polynominals (all in hardware of RFM22).
SPI interface
SPI interface is using 8 bit transfers. First transfer of each command contains address of RFM22 register and operation bit (Read/Write). Subsequent transfers contains data to be written into register(s), or readings from register(s).
Each transfer may consist of single write/read command, or may be a burst write/read.
1. Single write command :
nSEL=0 | [1][REG_ADDR 0..0x7F] | [DATA_BYTE]sdo | nSEL=1
2. Single read command :
nSEL=0 | [0][REG_ADDR 0..0x7F] | [REG_VAL]sdi | nSEL=1
3. Burst write command :
nSEL=0 | [1][REG_ADDR 0..0x7F] | [DATA_BYTE0]sdo | [DATA_BYTE1]sdo | [DATA_BYTEn]sdo |nSEL=1
NOTE : Consecutive bytes are written to addresses starting at REG_ADDR, incrementing after each byte, unless REG_ADDR is 0x7F.
If REG_ADDR is 0x7F (FIFO gateway), incrementing is disabled, and whole transfer is going through 0x7F register – it allows to burst read/write FIFO in single block.
4. Burst read command :
nSEL=0 | [0][REG_ADDR 0..0x7F] | [REG_VAL0]sdi | [REG_VAL1]sdi | [REG_VALn]sdi |nSEL=1
The same notes as for burst write applies to burst read command.
Example of setting READY mode of operation :
nSEL=0 | 0x87 | 0x01 | nSEL=1
It means, that write (MSB bit (0x80) is set in address) is performed to 0x07 register (mode of operation), with value 0x01 (IDLE, READY).
RFM22 internal registers
When you look into datasheets, you may feel a little bit lost 🙂
Yeah, there are near 127 registers in this little module, but many of them are set-and-forget ones.
Moreover, there are MSExcel spreadsheet calculators, providing you with set of calculated values for
your RFM22 module. You only have to enter desired transmittion parameters.
More important registers are :
more coming soon… need some sleep 🙂
—————————————————————————————————
RFM22 interface library v.0.0.1 pre-alpha version 🙂
http://rapidshare.com/files/424493489/RFM22.ZIP
Tested with PIC32MXs, 20kbauds configured, 868MHz operation, interrupt operation (INT2) currently switched off.
PIC32 & its ADC10 module
It should be a piece of cake, but when you look into details …
Even if you look deeper into datasheets, you wouldn’t find the statement – DO NOT USE PGED1/C1 to debug your application if using ADC module.
Why ? I don’t know, but it seems to have something with VRef+/- function bound to PGED1/C1 pins (AN0/AN1).
Yeah, I’ve set VCFG correctly to AVDD/AVSS…
Jizz, two days lost…
Using Tearing Line Output from Nokia LCD
Nokia LCDs mentioned in this blog has tearing line output feature. It can be used to synchronize MCU->LCD writes with LCD display memory scan pointer.
What for? To prevent showing partially content we want to write to LCD’s display RAM.
Problems :
A) your MCU should be fast enough to stream whole framebuffer to LCD within TE (Tearing Effect line output) pulse -> then, LCD read pointer won’t start scanning the frame before whole MCU->LCD transfer ends.
OR:
B) your MCU should be fast enough to stream whole framebuffer to LCD between n and n+2 TE pulses -> then LCD read pointer starts before write to LCD display memory occurs and write pointer will be always behind read pointer of LCD’s memory controller.
If your MCU isn’t fast enough to meet these requirements, tearing would always appear…
TE pulse width is given by LCD’s frame refresh rate (default ~60Hz).
At 60Hz frame scan time is about 16ms. Full frame is 320x240x3 bytes = 230400 bytes. To be able to write full framebuffer during two frame scan time (option B) your MCU should have data computation & throughput speed ~7 MB/s…
Well, it is impressive in the world of cheap and easy MCUs, even PIC32s 🙂