Arduino 0008 pins question...

Arduino 0008 is looking great! Thanks to all involved.

Now that I can, I'm trying to adapt my software TWI library to use any of the pins. What I'd like to do is call the constructor with the pins I want to use, get the port, pin and ddr for each and save them, then use cbi and sbi for bit-banging. My constructor looks like this:

#include "Twi.h"

// Constructor
Twi::Twi(uint8_t pinSDA, uint8_t pinSCL) {
twi_port_sda = digital_pin_to_port(pinSDA);
twi_pin_sda = digital_pin_to_bit_mask(pinSDA);
twi_ddr_sda = port_to_mode(twi_port_sda);

twi_port_scl = digital_pin_to_port(pinSCL);
twi_pin_scl = digital_pin_to_bit_mask(pinSCL);
twi_ddr_scl = port_to_mode(twi_port_scl);
}

I am including pins_arduino.h, but the digital_pin... aren't resolved. Am I doing this wrong?

What I need is to get port, pin and ddr in a form for cbi and sbi to use.

Thanks!

D.

The functions have more Arduino-like names, here is a section of code from my programmer that uses those functions...

uint8_t mosibit = digitalPinToBitMask(MOSI);
  volatile uint8_t *mosiport = portOutputRegister( digitalPinToPort(MOSI));
  uint8_t sckbit = digitalPinToBitMask(SCK);
  volatile uint8_t *sckport = portOutputRegister( digitalPinToPort(SCK));
  uint8_t misobit = digitalPinToBitMask(MISO);
  volatile uint8_t *misopins = portInputRegister( digitalPinToPort(MISO));
  ....
    if ( v0 & i) *mosiport |= mosibit;  // set a bit in the port
    else *mosiport &= ~mosibit;   // clear a bit in the port
  ...
    result = ((result << 1) | ( (*misopins & misobit) ? 1 : 0));  // test a bit in the port

That isn't the cbi() and sbi() method, but I think you could use the ports in cbi() and sbi(). You might need to use one of the _SFR macros to do an offsest that the cbi() would then undo. That would need checking. The compiler will not make CBI or SBI opcodes in any event, that requires a compile time constant register and bit to use those faster instructions,.

Thanks jims,

I missed those functions, thanks for the example. Its great having all that stuff available. Also great having the analog in pins (PORTC) available for any use.

Thanks for your contribution to 0008!

D.

BTW, is there something about the built-in Wire library that doesn't work for you? We can try to improve it so you don't need to write your own TWI code.

Hi mellis,

I originally wrote the software TWI because I needed all the analog pins for analog input, so wanted to use spare digital pins for TWI. The only other advantage is that my software library is much smaller than Wire lib.

Wire works fine, though.

D.

Oh, awesome. I missed the "software" aspect of the library. Have you / will you post the code anywhere?

Hi mellis,

I'll be glad to share this code as soon as I figure out how to make my constructor set the pins to use for TWI. I'm still trying to figure out how to do this so I can use sbi and cbi. I have a version for 0007, but you have to hard-code the pins/ports in the library, and that's low-class.

I could code it using pinmode and digital read/write, but I'm trying to avoid the checking that these do to keep it fast. If you have any advice I could use it.

D.

P.S. If you would be interested in having a look at the code, I'd be glad to send it.

I'd use pinMode() in the constructor. It does some checking, but you only do it once so its no big deal. Also in the constructor I'd save the port,pin, and mask for the pins in instance variables. Then the rest of your operations will be very fast.

One note on constructors that has bitten me... The Arduino initialization routines run after your constructors, so you have to watch out for things being altered by the initialization code. I don't think the data direction registers are set in the initialization, but you might want to check if it seems your output pins are not being outputs. I know it forced me to add .begin() functions to a couple classes that use timers because the initialization code would overwrite their settings.

Hi jims,

The trouble is, I think, that I need to switch the SCL pin between input and output. TWI uses the SCL line for a sort of handshaking where the slave can hold it low if it isn't ready. So I need to do a:

cbi(TWI_DDR_SCL, bSCL) to release the line. If a slave isn't holding it low, the pullup will pull the line high.

then wait for the SCL line to go hi before I do anything else. The length of one clock pulse is about 2 microseconds. I'll try it using pinmode and digitalread/write and see if it works, but I worry about introducing any extra delays into the process.

Thanks!

D.

You can use portModeRegister() to get from a port to the data direction register for fast direction changes. I think a 1 in the bit position is output and a 0 is input.