Cannot ping EEPROM on PPDB
DavidZemon
Posts: 2,973
in Propeller 1
I'm trying to use the EEPROM on the Propeller Professional Development Board but have not been able to ping it. propeller-load is able to write my program to EEPROM successfully and verify it, so that means the EEPROM chip should be working, right?
The exact same binary is able to ping the EEPROM on my Quickstart board.
anyone have any idea why it's failing to ping on my PPDB?
The exact same binary is able to ping the EEPROM on my Quickstart board.
#include <PropWare/gpio/pin.h> using namespace PropWare; class I2CMaster { public: static const Pin::Mask DEFAULT_SCL_MASK = Pin::Mask::P28; static const Pin::Mask DEFAULT_SDA_MASK = Pin::Mask::P29; static const unsigned int DEFAULT_FREQUENCY = 400000; public: /** * @brief Create a basic I2C instance * * @param[in] sclMask Pin mask for the SCL pin (default value uses the EEPROM SCL line) * @param[in] sdaMask Pin mask for the SDA pin (default value uses the EEPROM SDA line) * @param[in] frequency Frequency to run the bus (default is highest standard I2C frequency of 400 kHz) */ I2CMaster (const Pin::Mask sclMask = DEFAULT_SCL_MASK, const Pin::Mask sdaMask = DEFAULT_SDA_MASK, const unsigned int frequency = DEFAULT_FREQUENCY) : m_scl(sclMask, Pin::Dir::IN), m_sda(sdaMask, Pin::Dir::IN) { this->set_frequency(frequency); //Set outputs low this->m_scl.clear(); this->m_sda.clear(); } /** * @brief Set the bus frequency * * @param[in] frequency Frequency in Hz to run the bus */ void set_frequency (const unsigned int frequency) { this->m_clockDelay = CLKFREQ / (frequency << 1); } /** * @brief Output a start condition on the I2C bus */ void start () const { this->half_clock(); this->m_scl.set(); this->m_sda.set(); this->m_scl.set_dir_out(); this->m_sda.set_dir_out(); this->half_clock(); this->m_sda.clear(); this->half_clock(); this->m_scl.clear(); } /** * @brief Output a stop condition on the I2C bus */ void stop () const { this->m_sda.clear(); this->m_scl.clear(); this->half_clock(); this->m_scl.set_dir_in(); this->half_clock(); this->m_sda.set_dir_in(); } /** * @brief Output a byte on the I2C bus. * * @param[in] byte 8 bits to send on the bus * * @return true if the device acknowledges, false otherwise */ bool send_byte (const uint8_t byte) const { int result = 0; int dataMask = 0; int nextCnt = 0; int temp = 0; __asm__ volatile( FC_START("PutByteStart", "PutByteEnd") /* Setup for transmit loop */ " mov %[_dataMask], #256 \n\t" /* 0x100 */ " mov %[_result], #0 \n\t" " mov %[_nextCnt], cnt \n\t" " add %[_nextCnt], %[_clockDelay] \n\t" /* Transmit Loop (8x) */ //Output bit of byte "PutByteLoop%=: " " shr %[_dataMask], #1 \n\t" // Set up mask " and %[_dataMask], %[_dataByte] wz,nr \n\t" // Move the bit into Z flag " muxz dira, %[_SDAMask] \n\t" //Pulse clock " waitcnt %[_nextCnt], %[_clockDelay] \n\t" " andn dira, %[_SCLMask] \n\t" // Set SCL high " waitcnt %[_nextCnt], %[_clockDelay] \n\t" " or dira, %[_SCLMask] \n\t" // Set SCL low //Return for more bits " djnz %[_dataMask], #" FC_ADDR("PutByteLoop%=", "PutByteStart") " nr \n\t" // Get ACK " andn dira, %[_SDAMask] \n\t" // Float SDA high (release SDA) " waitcnt %[_nextCnt], %[_clockDelay] \n\t" " andn dira, %[_SCLMask] \n\t" // SCL high (by float) " waitcnt %[_nextCnt], %[_clockDelay] \n\t" " mov %[_temp], ina \n\t" //Sample input " and %[_SDAMask], %[_temp] wz,nr \n\t" // If != 0, ack'd, else nack " muxz %[_result], #1 \n\t" // Set result to equal to Z flag (aka, 1 if ack'd) " or dira, %[_SCLMask] \n\t" // Set scl low " or dira, %[_SDAMask] \n\t" // Set sda low FC_END("PutByteEnd") : // Outputs [_dataMask] "=&r"(dataMask), [_result] "=&r"(result), [_nextCnt] "=&r"(nextCnt), [_temp] "=&r"(temp) : // Inputs [_SDAMask] "r"(this->m_sda.get_mask()), [_SCLMask] "r"(this->m_scl.get_mask()), [_dataByte] "r"(byte), [_clockDelay] "r"(m_clockDelay)); return (bool) result; } /** * @brief Test for the Acknowledge of a device by sending start and the slave address. * * Useful for polling the bus and seeing what devices are available. Ping uses the following format: * * +--------+----+-------+-----+----+ * | Master | ST | SAD+W | | SP | * | Slave | | | SAK | | * +--------+----+-------+-----+----+ * * @param[in] device 7-bit shifted address device (in bits 7-1, not 6-0) * * @return true if ack was received, false otherwise */ bool ping (const uint8_t device) const { this->start(); bool result = this->send_byte(device); this->stop(); return result; } private: /** * @brief Wait for half of one clock period, or the minimum waiting period * * When compiled with the compact memory model (CMM), it is easily possible that half of the waiting period * is less time than it takes to execute the waitcnt() function. Therefore, this will either wait for half of * the clock's period or a single `nop` instruction may be run if the clock is too fast. */ void half_clock () const { #ifdef __PROPELLER_CMM__ if (500 > m_clockDelay) __asm__ volatile ("nop;"); else waitcnt(m_clockDelay + CNT); #else waitcnt(this->m_clockDelay + CNT); #endif } private: const Pin m_scl; const Pin m_sda; unsigned int m_clockDelay; }; int main () { const Pin::Mask LED_PIN_MASK = Pin::Mask::P16; const Pin led(LED_PIN_MASK, Pin::Dir::OUT); const I2CMaster i2c; bool eepromAck; do { eepromAck = i2c.ping(0x50 << 1); if (!eepromAck) { led.toggle(); waitcnt(CNT + 50 * MILLISECOND); } } while (!eepromAck); while (1) { led.toggle(); waitcnt(CNT + 200 * MILLISECOND); } }
anyone have any idea why it's failing to ping on my PPDB?
Comments
That did it! Thanks