Does anybody have a hint helping to port the sparkfun ATMEL library for their Authentication chip:
The only show stopper are the Arduino macros like: digitalPinToBitMask(), digitalPinToPort(), pinModeRegister(). … see below:
// atsha204Class Constructor
// Feed this function the Arduino-ized pin number you want to assign to the ATSHA204's SDA pin
// This will find the DDRX, PORTX, and PINX registrs it'll need to point to to control that pin
// As well as the bit value for each of those registers
atsha204Class::atsha204Class(uint8_t pin)
{
device_pin = digitalPinToBitMask(pin); // Find the bit value of the pin
uint8_t port = digitalPinToPort(pin); // temoporarily used to get the next three registers
// Point to data direction register port of pin
device_port_DDR = portModeRegister(port);
// Point to output register of pin
device_port_OUT = portOutputRegister(port);
// Point to input register of pin
device_port_IN = portInputRegister(port);
}
Are there already some standard hints how to replace that calls and come to the the same result?
@sparki, the Core does not use the same mechanisms for accessing bits on the GPIO ports. Instead, there is a bitmap structure and are bit set and bit reset registers as follows:
to set a bit high: PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin
to set a bit low: PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin
You need to make sure you set the pin to OUTPUT mode first using the pinMode(pin,OUTPUT) function. A valid value for pin is D0…D7, A0…A7.
@ppkay, Ok, thanks a lot!
I have already studied the Adafruit SSD1306:SPI init porting and compared it to the original. Your answer does now help to understand, I will try it.
…Coming back - another question:
I have tried to port the send method. AVR needs at that point a special timing. Do you think I can sum up all micros and did the delay at the end like:
Assuming this could be the right spark way sending data over that GPIO pin, reading is the next task:
At here, I found an analgous GPIO read; and here I found a a great helping example from @BDub.
Now I go with the following changes:
uint8_t atsha204Class::swi_receive_bytes(uint8_t count, uint8_t *buffer) {
//--------------------------------------------------------------------- JH -
uint8_t status = SWI_FUNCTION_RETCODE_SUCCESS;
uint8_t i;
uint8_t bit_mask;
uint8_t pulse_count;
uint8_t timeout_count;
// Disable interrupts while receiving.
noInterrupts(); //swi_disable_interrupts();
// Configure signal pin as input.
pinMode(device_pin, INPUT); //JH
//AVR *device_port_DDR &= ~device_pin;
// Receive bits and store in buffer.
for (i = 0; i < count; i++) {
for (bit_mask = 1; bit_mask > 0; bit_mask <<= 1) {
pulse_count = 0;
// Make sure that the variable below is big enough.
// Change it to uint16_t if 255 is too small, but be aware that
// the loop resolution decreases on an 8-bit controller in that case.
timeout_count = START_PULSE_TIME_OUT;
// Detect start bit.
while (--timeout_count > 0) {
// Wait for falling edge.
//AVR if ((*device_port_IN & device_pin) == 0)
//AVR break;
if((PIN_MAP[device_pin].gpio_peripheral->IDR & //JH
PIN_MAP[device_pin].gpio_pin) == 0) //JH
break;
}
if (timeout_count == 0) {
status = SWI_FUNCTION_RETCODE_TIMEOUT;
break;
}
do {
// Wait for rising edge.
//AVR if ((*device_port_IN & device_pin) != 0) {
if((PIN_MAP[device_pin].gpio_peripheral->IDR & //JH
PIN_MAP[device_pin].gpio_pin) != 0) { //JH
//faster than "pulse_count++".
pulse_count = 1;
break;
}
} while (--timeout_count > 0);
if (pulse_count == 0) {
status = SWI_FUNCTION_RETCODE_TIMEOUT;
break;
}
// Trying to measure the time of start bit and calculating the timeout
// for zero bit detection is not accurate enough for an 8 MHz 8-bit CPU.
// So let's just wait the maximum time for the falling edge of a zero bit
// to arrive after we have detected the rising edge of the start bit.
timeout_count = ZERO_PULSE_TIME_OUT;
// Detect possible edge indicating zero bit.
do {
if((PIN_MAP[device_pin].gpio_peripheral->IDR & //JH
PIN_MAP[device_pin].gpio_pin) == 0) { //JH
//AVRif ((*device_port_IN & device_pin) == 0) {
// For an Atmel microcontroller this might be faster than "pulse_count++".
pulse_count = 2;
break;
}
} while (--timeout_count > 0);
// Wait for rising edge of zero pulse before returning. Otherwise we might interpret
// its rising edge as the next start pulse.
if (pulse_count == 2) {
do {
if((PIN_MAP[device_pin].gpio_peripheral->IDR & //JH
PIN_MAP[device_pin].gpio_pin) != 0) //JH
//AVR: if ((*device_port_IN & device_pin) != 0)
break;
} while (timeout_count-- > 0);
}
// Update byte at current buffer index.
else
buffer[i] |= bit_mask; // received "one" bit
}
if (status != SWI_FUNCTION_RETCODE_SUCCESS)
break;
}
interrupts(); //swi_enable_interrupts();
if (status == SWI_FUNCTION_RETCODE_TIMEOUT) {
if (i > 0)
// Indicate that we timed out after having received at least one byte.
status = SWI_FUNCTION_RETCODE_RX_FAIL;
}
return status;
}
@sparki, I was just looking at the specs for the ATSHA204. It is basically an I2C device but the 3 pin version used on the Sparkfun breakout, it uses single pin communications. This explains the elaborate “bit-banging” library.
So, the answer to your question regarding delays is no, you cannot sum them up at the end. Each delay provides very specific bit-delay timing to create a correctly timed bit stream to the device. Because this version of the ATSHA204 does not use 2 pins for full I2C operation, all communications must be done in software (ie no hardware assistance).
Looking at the timing diagrams for the chip, I believe the direct port commands I gave you are not absolutely necessary and you could use digitalWrite() and digitalRead() instead. However timing is always tricky. Would you like me take a crack at porting the library?
Yes, You ae right, the I2C version I would also prefer - but it was so easy to get an sparffun breakout from it.
I have adapted the last method I saw ..
... then I will test. For me it its just for fun and to learn how to do do the low level things -
But ... if you offer your knowledge, I would be happy.
No spark - no fun!
... coming back:
I have done some tests: No success!
I have realized the recommendations/considerations from @peekay123 and done the GPIO handling in the common standard way with digitalRead(), digitalWrite() - but the device does not want to react at the wakeup command and in the following.
OK: No sucess at the moment - may be later - with new ideas!
@Sparki, I took a crack at porting the code here in my repo. I kept the original Arduino code and used conditional compiling to make it Spark specific.
I used the standard digitalRead/Write() commands since they are very fast. Also note that I set the device pin to D4, which you can change of course. Let me know if that works for you
Thanks for your crack support - super service!
OK I was mostly on the right way - found only a small mistake!
But it’s a pitty, the device wont reply (your source in charge, enriched with the send/read pin’s settings): Every time when its time to speech there is no traffic on the data line.My short suggestions are: I2C would be the better first approach to handle the timming stuff by a proper protocol.
I should start with the wakeup - but I have to break for some hours.
cheers and many thanks.
@peekay123 OK, I had a look to the breakout schematic. There it is a SDA pullup (100k) I think this is correct. Additionaly I had verified the timing of the wakeup procedure with my logic.
All seems correct:
more than 60us (72us) wakeup down,
wait for 2,5msec,
sending 0x88
listening… but time out!
This is also reflected by the serial output:
Sending a Wakup Command. Response should be:
4 11 33 43:
Response is:
0 0 0 0
Asking the SHA204’s serial number. Response should be:
1 23 x x x x x x x EE
Response is:
4E 16 E2 1A 2D 1C 0 0 0
Something does not match and I do not have a new idea at the moment.
Other guys seems also do not have success.
I have tried to get a I2C sample at ATMEL, but it seems this is only possible for a company.