For powering the nrf24l01+ module, a 3.3v regulator could be used, but a cheaper and simpler way is to drop a 5V supply to 3V using a 20mA-rated red led. Most red LEDs have a forward voltage drop between 1.8 and 2.2V, leaving 3.2-2.8V for the nrf, which is well within the 1.9-3.6V requirement.
Controlling CE without using a pin on the AVR is also easy: just tie it high. In my setup function, I set Mirf.cePin = 7 as a dummy since the tiny85 only has pins 0-6. I later commented out the digitalWrite calls in Nrf24l::ceHi() and ceLow(), and removed the Mirf.cePin line from setup() which cut down on the size of my compiled sketch.
I initially thought the CSN line could be tied low, but when I tried it my test sketch was not getting a valid status back from the nrf module. I also found section 8.3.1 of the datasheet: "Every new command must be started by a high to low transition on CSN." So in order to control the nrf with just 3 pins, CSN needs to be multiplexed with one (or more) of SCK, MOSI, or MISO. After a few different ideas, I came up with this circuit:
When SCK on the ATtiny85 goes high for several microseconds, C1 will charge through R1 and bring CSN high. If SCK is brought low for several microseconds before being used to clock the SPI data, C1 will discharge through D1 and bring CSN low. High pulses on SCK of less than a few microseconds during communication with the nrf won't last long enough to charge C1, so CSN will stay low.
To support the multiplexed SCK/CSN, I modified Mirf.cpp as follows:
PORTB |= (1<<PINB2); // SCK->CSN HIGH
delayMicroseconds(64); // allow csn to settle
PORTB &= ~(1<<PINB2); // SCK->CSN LOW
delayMicroseconds(8); // allow csn to settle
The circuit still worked with a 32us delay in csnHi and 8us in csnLow, but I doubled those values to have a good safety margin. The delays could be reduced with a smaller capacitor for C1. Going lower than .01uF could risk CSN going high during the high clock pulses of SCK.
When connecting the nrf module to a tiny85, connect MISO(pin7) on the module to MOSI/DI(PB0), and not MISO/DI(PB1). Here's the connections required:
nrf module ATtiny85 pin
SCK(5) PB2 (physical pin 7)
MOSI(6) PB1 (physical pin 6)
MISO(7) PB0 (physical pin 5)
I also changed TinyDebugSerial.h to define TINY_DEBUG_SERIAL_BIT 5, and connected pb5 to the Rx line of my ttl serial module.
Finally, here's my test sketch. When it runs, it reports a status of 'E', which is the reset value of the status register according to the datasheet. If you connect things wrong it will usually report 0 or FF.
Mirf.spi = &MirfHardwareSpi85;
Serial.print("\nMirf status: ");
nrfStatus = Mirf.getStatus();
// do back-to-back getStatus to test if CSN goes high
nrfStatus = Mirf.getStatus();
I've noticed that power usage on the nRF modules shoots up if I leave any inputs (CSN, SCK, MOSI) floating. With my circuit above CSN will never float, but SCK and MOSI should be pulled high or low when not in use, especially for battery-powered devices.
I've written another post titled nRF24l01+ reloaded with more details on controlling these modules.
I've figured out a way to control nRF modules with just 2 pins using custom bit-banged SPI routines.