UIMENU and I2C respectively SPI
Hi all,
after playing around with UI functions i have some questions i couldn´t figure out on my own.
for example the UI_MATRIX_ACTIONS.
seems to be needed only with matrix keyboard , am i correct?
I2C buttons , is it possible to add a second/third I2C peripheral using the integrated I2C driver?
if yes , maybe a short example would be helpful (no need to get the job done by somebody i just hope for a starting point)
in UIconfig there is the possibility to connect buttons via MCP23017 is it possible to switch to the SPI pendant MCP23S17?
would be much faster.May be somebody did that, Software SPI would be nice.
Maybe there is someone in the forum to give me a guide.
Thank´s in advance,
RAyWB
after playing around with UI functions i have some questions i couldn´t figure out on my own.
for example the UI_MATRIX_ACTIONS.
seems to be needed only with matrix keyboard , am i correct?
I2C buttons , is it possible to add a second/third I2C peripheral using the integrated I2C driver?
if yes , maybe a short example would be helpful (no need to get the job done by somebody i just hope for a starting point)
in UIconfig there is the possibility to connect buttons via MCP23017 is it possible to switch to the SPI pendant MCP23S17?
would be much faster.May be somebody did that, Software SPI would be nice.
Maybe there is someone in the forum to give me a guide.
Thank´s in advance,
RAyWB
Comments
void uiInitKeys()
and
void uiCheckKeys(uint16_t &action)
so it is possible to add any logic you want for extra key functions. The I2C solution implemented is just mixing display and free pins for buttons to get them more or less for free.
what i´m thinking about is implementing user specific hardware , the idea came up as you implemented the analog input
to read buttons.
That´s what i described in my post "manual positioning/jogwheel". I added now some buttons for homing , setting positions to zero, single probing and so on just functions i want t control without menu and without computer connected. and therefore i use a hacked gamepad.
so now my thoughts are drifting to adding an external A/D converter and/or additional Portextender like 23017.
i want to insert the code to uiconfig similar to your :
#if UI_DISPLAY_I2C_CHIPTYPE==1 // will change this to check one pin if gamepad is connected
HAL::i2cStartWait(UI_DISPLAY_I2C_ADDRESS+I2C_WRITE); // have to change to address of my hardware
HAL::i2cWrite(0x12); // GIOA
HAL::i2cStop();
HAL::i2cStartWait(UI_DISPLAY_I2C_ADDRESS+I2C_READ);
uint16_t keymask = HAL::i2cReadAck();
keymask = keymask + (HAL::i2cReadNak()<<8);
#endif
i know i can´t use same address and variables so i have to change the names, my basic intention is reducing wires to my
hacked gamepad just placing the A/D converter to the gamepad side. from Hardware view i know how to handle the I2C for longer distances , that will not be an issue.
Thanks for your support and by the way thank you for your absolute great Job and support !!
One more question please , regarding the GITHUB repository , are there some special rules to create a fork of your software?
I don´t have an account yet , but in order to share my modifications i´m thinking about that.
best regards,
RAyWB
i tried to use the existing code as it is but could not succeed i used MCP23017 but it seems there is some mismatch when using NON-I2C Display. there seem to be multiple I2C Routines (found some in HAL , some in U8Glib) so i´m pretty confused now.
So basically the UI_Display I2C routines come from u8glib?
I also cannot follow how the UI_KEYS_I2C_BUTTON_LOW(_BV(1),UI_ACTION_OK) works.
so there is the I2C read , returning a value to variable keymask.
_BV(1) is a bit shift operation defined in HAL , pinnumber means value of shift
but i cannot find a function UI_KEYS_I2C_BUTTON_LOW...
Can you clarify please?
if i use arduino wire library it works, may be there is a trap i couldn´t see
can you tell me what´s wrong?
// CODE:
#include <Wire.h> //for arduino lib
#define MCP_IN_ADDRESS 0x20
#define MCP_OUT_ADDRESS 0x24
#define MCP23017_IODIRA 0x00
#define MCP23017_GPIOA 0x12
#define MCP23017_IODIRB 0x01
#define MCP23017_GPIOB 0x13
#define MCP23017_KEYS_I2C_BUTTON_LOW(pin,action_) if((keymask1 & pin)==0) action=action_;
// cannot get the following running . seems like watchdog timeout happens
#define COMPILE_I2C_DRIVER
HAL::i2cInit(100000);
HAL::i2cStart(MCP_IN_ADDRESS<<1 + I2C_WRITE);
HAL::i2cWrite(MCP23017_IODIRA); // GPIOA
HAL::i2cWrite(0xFF); // all INPUTS
HAL::i2cStop();
HAL::i2cStart(MCP_IN_ADDRESS<<1 + I2C_WRITE);
HAL::i2cWrite(MCP23017_IODIRB); // GPIOB
HAL::i2cWrite(0xFF); // all INPUTS
HAL::i2cStop();
HAL::i2cStart(MCP_IN_ADDRESS<<1 + I2C_READ);
uint16_t keymask1 = HAL::i2cReadAck();
keymask1 = keymask1 + (HAL::i2cReadNak()<<8);
HAL::i2cStop();
*/
//###########################################################################
//following code using arduino wire library is running well
Wire.begin();
Wire.beginTransmission(MCP_IN_ADDRESS);
Wire.write(MCP23017_IODIRA);
Wire.write(0xFF);
Wire.endTransmission();
Wire.beginTransmission(MCP_IN_ADDRESS);
Wire.write(MCP23017_IODIRB);
Wire.write(0xff);
Wire.endTransmission();
Wire.beginTransmission(MCP_IN_ADDRESS); //
Wire.write(MCP23017_GPIOA);
Wire.endTransmission();
Wire.requestFrom(MCP_IN_ADDRESS, 2);
uint16_t keymask1 = Wire.read();
keymask1 = keymask1 + (Wire.read()<<8);
//following witch 2nd MCP23017 just for testing
//OUTPUTS
Wire.beginTransmission(MCP_OUT_ADDRESS);
Wire.write(MCP23017_IODIRA);
Wire.write(0x00);
Wire.endTransmission();
Wire.beginTransmission(MCP_OUT_ADDRESS);
Wire.write(MCP23017_IODIRB);
Wire.write(0x00);
Wire.endTransmission();
Wire.beginTransmission(MCP_OUT_ADDRESS);
Wire.write(MCP23017_GPIOA);
Wire.write(keymask1>>8); // write something just to see that something happens
Wire.endTransmission();
//#############################################################################
MCP23017_KEYS_I2C_BUTTON_LOW(_BV(1),UI_ACTION_OK); // push button, connects gnd to pin
MCP23017_KEYS_I2C_BUTTON_LOW(_BV(3),UI_ACTION_BACK); // push button, connects gnd to pin
MCP23017_KEYS_I2C_BUTTON_LOW(_BV(8),UI_ACTION_MENU_QUICKSETTINGS+UI_ACTION_TOPMENU); // push button, connects gnd to pin
MCP23017_KEYS_I2C_BUTTON_LOW(_BV(15),UI_ACTION_MENU_EXTRUDER+UI_ACTION_TOPMENU); // push button, connects gnd to pin
MCP23017_KEYS_I2C_BUTTON_LOW(_BV(6),UI_ACTION_MENU_POSITIONS+UI_ACTION_TOPMENU); // push button, connects gnd to pin
#define COMPILE_I2C_DRIVER
HAL::i2cInit(100000);
HAL::i2cStart(MCP_IN_ADDRESS<<1 + I2C_WRITE);
HAL::i2cWrite(MCP23017_IODIRA); // GPIOA
HAL::i2cWrite(0xFF); // all INPUTS
HAL::i2cStop();
HAL::i2cStart(MCP_IN_ADDRESS<<1 + I2C_WRITE);
HAL::i2cWrite(MCP23017_IODIRB); // GPIOB
HAL::i2cWrite(0xFF); // all INPUTS
HAL::i2cStop();
HAL::i2cStart(MCP_IN_ADDRESS<<1 + I2C_WRITE);
HAL::i2cWrite(MCP23017_GPIOA ); // GPIOA
HAL::i2cStop();
HAL::i2cStart(MCP_IN_ADDRESS<<1 + I2C_READ);
uint16_t keymask1 = HAL::i2cReadAck();
keymask1 = keymask1 + (HAL::i2cReadNak()<<8);
HAL::i2cStop();
i have due board + st7920 spi display+ encoder via direct(non i2c) pins.
even if i just try to add i2c beeper without i2c buttons and without i2c encoder it doesn´t work.
just pulled new files from github yesterday and only set beeper to i2c
just one thing happens.. if i move the encoder the firmware hangs and reboots after a few seconds
any ideas?
as my coding knowledge is limited i´ll continue the due project with the wire library but
I´ll try the code on a mega2560 and inform you the result
on mega2560 :
MCP23017 doesn´t work , found a mismatch in ui.cpp line 72 : HAL::i2cWrite( 0x14);
changed to HAL::i2cWrite( 0x12);
beeper works now once, but it takes a few seconds without any action to get triggered again.
switched over to PCF8574:
beeper works as expected.
seems there is something wrong with MCP23017 implementation
switched over to DUE and PCF8574 :
no beeper function , but no hanging firmware....
anyway , I2C EEPROM works
I´m totally confused now
// set direction of pins
HAL::i2cStart(UI_DISPLAY_I2C_ADDRESS + I2C_WRITE);
HAL::i2cWrite(0); // IODIRA
HAL::i2cWrite(~(UI_DISPLAY_I2C_OUTPUT_PINS & 255));
HAL::i2cWrite(~(UI_DISPLAY_I2C_OUTPUT_PINS >> 8));
HAL::i2cStop();
// Set pullups according to UI_DISPLAY_I2C_PULLUP
HAL::i2cStart(UI_DISPLAY_I2C_ADDRESS+I2C_WRITE);
HAL::i2cWrite(0x0C); // GPPUA
HAL::i2cWrite(UI_DISPLAY_I2C_PULLUP & 255);
HAL::i2cWrite(UI_DISPLAY_I2C_PULLUP >> 8);
HAL::i2cStop();
but why doesn´t work pcf8574 on due?
i use same uiconfiguration on mega and due
only difference i found :
eeprom uses void HAL::i2cStartAddr(unsigned char address_and_direction, unsigned int pos)
other i2c stuff uses : void HAL::i2cStartWait(unsigned char address_and_direction)
respectively : unsigned char HAL::i2cStart(unsigned char address_and_direction)
these functions differ , but that´s out of my knowledge
firmware hangs when i use #define UI_HAS_I2C_KEYS.
so if i have non i2c buttons and i2c buttons , doesn´t that work?
i´ll continue searching the next days , need a little break now
i know about the special level shifters , i use them in another application
driving a Display on a 10m long wire through noisy environment (here i had to shift up to 12V and back to 5 after the wire).
but to your question:
settings for EEProm (written in userpins.h:)
#define SDA_PIN 20
#define SCL_PIN 21
#define TWI_CLOCK_FREQ 100000
#define EEPROM_SERIAL_ADDR 0x50 // 7 bit i2c address (without R/W bit)
#define EEPROM_PAGE_SIZE 64 // page write buffer size
#define EEPROM_PAGE_WRITE_TIME 7 // page write time in milliseconds (docs say 5ms but that is too short)
// specify size of eeprom address register
// TWI_MMR_IADRSZ_1_BYTE for 1 byte, or TWI_MMR_IADRSZ_2_BYTE for 2 byte
#define EEPROM_ADDRSZ_BYTES TWI_MMR_IADRSZ_2_BYTE
#define EEPROM_AVAILABLE 1
so as i wrote above: PCF8574 is running for beeper , just if i enable #define UI_HAS_I2C_KEYS. firmware hangs ,
but anyway i didn´t get the MCP23017 running .
so my current status :
I2c EEProm : running
PCF8574 :running for Beeper
MCP23017 not running via HAL routines if i use Wire library its ok
But using Wire seems to cause conflict to HALroutines , PCF8574 Beeper(HAL) gets not reliable.
So I´m still searching using the try and error method
(beeper address is same as key address)
if i replace the HAL code in uiCheckSlowKeys by Wire code
as follows beeperworks with HAL,Buttons with Wire code... Strange
void uiCheckSlowKeys(uint16_t &action) {
#if defined(UI_HAS_I2C_KEYS) && UI_HAS_KEYS!=0
#if UI_DISPLAY_I2C_CHIPTYPE==0
Wire.requestFrom(0x27, 1);
uint8_t keymask = Wire.read();
Wire.endTransmission();
// HAL::i2cStartWait(UI_I2C_KEY_ADDRESS+I2C_READ);//key address is 0x4e
// uint8_t keymask = HAL::i2cReadNak(); // Read current key mask
#endif
after that i changed code for beep , for a better overview i sorted code by beeper type
and added routine for MCP23017 to PCF8574 beep routine.
for my understanding the wire stuff should do exactly the same as Hal stuff,
but for mcp 23017 only the wire version works
see code:
#if BEEPER_TYPE==2
#if UI_DISPLAY_I2C_CHIPTYPE==0
//
for(uint8_t i=0; i < count; i++)
{
HAL::i2cStartWait(BEEPER_ADDRESS +I2C_WRITE);
#if BEEPER_ADDRESS == UI_DISPLAY_I2C_ADDRESS
HAL::i2cWrite(uid.outputMask & ~BEEPER_PIN);
#else
HAL::i2cWrite(~BEEPER_PIN);
#endif
HAL::i2cStop();
/*
//######## compare #######
//initialize MCP23017
Wire.beginTransmission(0x24);
Wire.write(0x00);//IODIRA
Wire.write(0x00);//all OUTPUT
Wire.write(0x00);//all OUTPUT
Wire.endTransmission();
//write to GPIOAB
Wire.beginTransmission(0x24);
Wire.write(0x12);//GPIOA
Wire.write(255);// all on,Reg counter automatically to 0x13
Wire.write(255);//all on
Wire.endTransmission();
//##### wire code runs the 23017 ######
*/
//##### HAL CODE NOT #####
// initialize MCP23017
HAL::i2cStartWait(0x48 + I2C_WRITE);
HAL::i2cWriting(0x00);//IODIRA
HAL::i2cWriting(0x00);
HAL::i2cWrite(0x00);
HAL::i2cStop();
//write to GPIOAB
HAL::i2cStartWait(0x48 + I2C_WRITE);
HAL::i2cWriting(0x12); // Start at port a
HAL::i2cWriting(255);//(BEEPER_PIN) | uid.outputMask);
HAL::i2cWrite(255);//((BEEPER_PIN) | uid.outputMask)>>8);
HAL::i2cStop();
//#######################
HAL::delayMilliseconds(duration);
HAL::i2cStartWait(BEEPER_ADDRESS +I2C_WRITE);
#if BEEPER_ADDRESS == UI_DISPLAY_I2C_ADDRESS
HAL::i2cWrite((BEEPER_PIN) | uid.outputMask);
#else
HAL::i2cWrite(255);
#endif
HAL::i2cStop();
//######
HAL::i2cStartWait(0x48 + I2C_WRITE);
HAL::i2cWriting( 0x12); // Start at port a
HAL::i2cWriting(0);
HAL::i2cWrite(0);
HAL::i2cStop();
//######
/*
Wire.beginTransmission(0x24);
Wire.write(0x12);
Wire.write(0);
Wire.write(0);
Wire.endTransmission();
*/
HAL::delayMilliseconds(duration);
}
#endif
so for me now it seems problem located in Hal... but i have no idea where. i tried to compare arduino wire.cpp with the Hal stuff but that is absolutely out of my coding limits.
Do you have some ideas? or the guy who implemented the i2c for due?
kind regards
On Due no way via HAL , just EEProm and Beeper onPCF8574
there are a few changes necessary , to meet the specs in ATMEL Datasheet.
The I2C EEprom works because of different/additional use of the existing HAL routines.
I´ll send a pull request in the next days so you can decide to implement or not.
I changed the routines to meet ATMEL Datasheet but unfortunately it will affect a couple of files which are
momentarily not Hardware specific.
To avoid that i think it´should possible to implement Arduinos Wire Library to keep code as it is,by just implementing
the Wire stuff in HAL.
Anyway , MCP23017 based controllers/Displays will not work with the actual I2C implementation, also reading PCF8574 is not possible.
Kind regards,
RAyWB
PCF8574, 1 Byte writing was possible)
some errors in other i2c routines , removed for example writes to read-only registers.
modified i2cwrite (removed return in i2cwrite as it is not used and blocked 2nd byte reading for mcp23017)
removed i2cwriting,i2cfinished,i2ccompleted routines(added their code to the other routines,
so code is now working 1:1 to the AVR stuff,differences only in HAL no further modifications necessary.
(depends on changing the i2cwrite and removing i2cwriting).
test setup 2*MCP23017,1*PCF8574,1*24LC256 , working together, no conflicts.
(i use arduino version 1.67 and 1.68 to compile , no problems).
changes commented in code, see pull request #515
kind regards,
RAyWB