diff --git a/pic/MDR/I2C.c b/pic/MDR/I2C.c index 491f552..17a7dfe 100644 --- a/pic/MDR/I2C.c +++ b/pic/MDR/I2C.c @@ -1,47 +1,44 @@ /* software bit banging implementation * based on https://en.wikipedia.org/wiki/I2c example code + * + * there is no external pull-up on SCL, and the internal one is too weak + * SCL must be driven + * but that is ok as we are the only master + * there is an external pull-up on SDA, and the internal one is too weak + * SDA goes to 3V instead of 5V due to the external pull-up + * but the 24LC256 still seems to work */ #include "I2C.h" // Hardware-specific support functions that MUST be customized: -#define I2CSPEED 100 -void I2C_delay() -{ - volatile int v = 0; - int i; - for (i=0; i < I2CSPEED/2; i++) { - v; - } -} +/* even when doing nothing, the max speed will be 100kHz, while the chip supports 400kHz */ +#define I2C_delay() /* Set SCL as input and return current level of line, 0 or 1 */ bool read_SCL(void) { - PORTB |= SCL; /* set as input */ - WPUB |= SCL; /* enable pull-up */ - return (PORTB&SCL); + LATB |= SCL; /* set high (must be driven because no pull-up */ + return 1; } /* Set SDA as input and return current level of line, 0 or 1 */ bool read_SDA(void) { - PORTB |= SDA; /* set as input */ - WPUB |= SDA; /* enable pull-up */ - return (PORTB&SDA); + TRISB |= SDA; /* set as input */ + return (PORTB&SDA)!=0; } /* Actively drive SCL signal low */ void clear_SCL(void) { - PORTB &= ~SCL; /* set as output */ - PORTB &= ~SDA; /* set low */ + LATB &= ~SCL; /* set low */ } /* Actively drive SDA signal low */ void clear_SDA(void) { - PORTB &= ~SCL; /* set as output */ - PORTB &= ~SDA; /* set low */ + TRISB &= ~SDA; /* set as output */ + LATB &= ~SDA; /* set low */ } void arbitration_lost(void) @@ -111,51 +108,52 @@ void i2c_write_bit(bool bit) { // Read a bit from I2C bus bool i2c_read_bit(void) { - bool bit; - // Let the slave drive data - read_SDA(); - I2C_delay(); - while (read_SCL() == 0) { // Clock stretching - // You should add timeout to this loop - } - // SCL is high, now data is valid - bit = read_SDA(); - I2C_delay(); - clear_SCL(); - return bit; + bool bit; + // Let the slave drive data + read_SDA(); + I2C_delay(); + while (read_SCL() == 0) { // Clock stretching + + // You should add timeout to this loop + } + // SCL is high, now data is valid + bit = read_SDA(); + I2C_delay(); + clear_SCL(); + return bit; } // Write a byte to I2C bus. Return 0 if ack by the slave. -bool i2c_write_byte(bool send_start, - bool send_stop, - unsigned char byte) { - unsigned bit; - bool nack; - if (send_start) { - i2c_start_cond(); - } - for (bit = 0; bit < 8; bit++) { - i2c_write_bit((byte & 0x80) != 0); - byte <<= 1; - } - nack = i2c_read_bit(); - if (send_stop) { - i2c_stop_cond(); - } - return nack; +bool i2c_write_byte(bool send_start, bool send_stop, unsigned char byte) +{ + unsigned bit; + bool nack; + if (send_start) { + i2c_start_cond(); + } + for (bit = 0; bit < 8; bit++) { + i2c_write_bit((byte & 0x80) != 0); + byte <<= 1; + } + nack = i2c_read_bit(); + if (send_stop) { + i2c_stop_cond(); + } + return nack; } // Read a byte from I2C bus -unsigned char i2c_read_byte(bool nack, bool send_stop) { - unsigned char byte = 0; - unsigned bit; - for (bit = 0; bit < 8; bit++) { - byte = (byte << 1) | i2c_read_bit(); - } - i2c_write_bit(nack); - if (send_stop) { - i2c_stop_cond(); - } - return byte; +unsigned char i2c_read_byte(bool nack, bool send_stop) +{ + unsigned char byte = 0; + unsigned bit; + for (bit = 0; bit < 8; bit++) { + byte = (byte << 1) | i2c_read_bit(); + } + i2c_write_bit(nack); + if (send_stop) { + i2c_stop_cond(); + } + return byte; } diff --git a/pic/MDR/MDR.c b/pic/MDR/MDR.c index d00308a..4685a51 100644 --- a/pic/MDR/MDR.c +++ b/pic/MDR/MDR.c @@ -42,8 +42,8 @@ /* pin 18 is for a secret function, set by jumper WJ2, Vdd per default */ /* simple functions */ -#define led_off() PORTB |= LED -#define led_on() PORTB &= ~(LED) +#define led_off() LATB |= LED +#define led_on() LATB &= ~(LED) #define sleep() __asm sleep __endasm /* variables */ @@ -69,11 +69,9 @@ uint16_t __at(_CONFIG2) __CONFIG2 = _LVP_ON & /* enable low voltage programming _PLLEN_OFF & /* don't use 4X PLL, for longer timer */ _WRT_OFF; /* no flash write protect */ - /* initialize micro-conroller */ void init (void) { /* configure IO */ - NOT_WPUEN = 0; /* enable individual pull-ups */ ANSELA = 0; /* all pins are digital */ ANSELB = 0; /* all pins are digital */ TRISA |= RADIO; /* radio signal is an input */ @@ -118,6 +116,8 @@ void init (void) { * this PIC16F1847 offers hardware I2C, but not on those pins * so we also have to use software bit banging I2C */ + TRISB &= ~SCL; /* set as output (it must be driven because there is no pull-up */ + LATB |= SCL; /* set clock as high (default pull-up state) */ PEIE = 1; /* enable peripheral interrupt (for timer 2) */ GIE = 1; /* golablly enable interrupts */ @@ -161,6 +161,11 @@ static void interrupt(void) __interrupt 0 if (switches&SWITCH1) { /* switch 1 changed */ if (PORTB&SWITCH1) { /* switch 1 released */ led_off(); /* reset LED */ + i2c_write_byte(1,0,0xa0); + i2c_write_byte(0,1,0xa0); +// i2c_write_byte(0,1,0x17); +// i2c_write_byte(1,0,0xa1); +// i2c_read_byte(0,0); } else { /* switch 1 pressed */ led_on(); /* test LED */ } diff --git a/pic/MDR/Makefile b/pic/MDR/Makefile index 7efaa4b..f5e861f 100644 --- a/pic/MDR/Makefile +++ b/pic/MDR/Makefile @@ -15,9 +15,9 @@ OBJ := $(patsubst %.c,%.o,$(SRC)) all: compile flash -# flash program +# flash program (the board needs to power externally) flash: $(TARGET).hex - pk2cmd -PPIC$(PIC) -F$< -M -W -R + pk2cmd -P PIC$(PIC) -F $< -M -W -R # compile stages assembly: $(ASM) @@ -36,7 +36,7 @@ compile: hex gpasm -I . -o $@ -c $< $(TARGET).hex: $(OBJ) - gplink -w -r -s /usr/share/gputils/lkr/$(PIC)_g.lkr -I/usr/share/sdcc/lib/pic14 -I/usr/share/sdcc/non-free/lib/pic14 -I. -o $@ libsdcce.lib pic$(PIC).lib $< + gplink -w -r -s /usr/share/gputils/lkr/$(PIC)_g.lkr -I /usr/share/sdcc/lib/pic14 -I /usr/share/sdcc/non-free/lib/pic14 -I . -o $@ libsdcce.lib pic$(PIC).lib $(OBJ) # remove temporary files clean: