123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- /*
- * eeprom_i2c.c
- *
- * Copyright 2022 dh33ex <dh33ex@riseup.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
- * MA 02110-1301, USA or see <http://www.gnu.org/licenses/>.
- *
- *
- */
- #ifndef __msp430_h_
- #include <msp430.h>
- #endif
- #include "eeprom_i2c.h"
- int ptr_buf;
- char i2c_buffer[68];
- void EEPROM_init(unsigned char i2c_address) {
- /* setup B0 for I2C */
- UCB0CTL1 |= UCSWRST; /* put B0 in SW RST */
- UCB0CTL1 |= UCSSEL_2; /* choose SMCLK */
- UCB0BR0 = 10; /* set presalar to 10 */
- UCB0BR1 = 0;
- UCB0CTL0 |= UCMODE_3; /* put into I2C mode */
- UCB0CTL0 |= UCMST; /* set as master */
- UCB0I2CSA = i2c_address; /* set slave address */
- /* setup ports */
- P1SEL |= BIT7; /* P1.7 = SDA */
- P1SEL2 |= BIT7;
- P1SEL |= BIT6; /* P1.6 = SCL */
- P1SEL2 |= BIT6;
- UCB0CTL1 &= ~UCSWRST; /* take B0 out of SW RST */
- }
- void EEPROM_write_setup(void) {
- UCB0CTL1 |= UCTR; /* set transmit mode */
- IFG2 &= ~UCB0TXIFG; /* clear transmit interrupt flag */
- IE2 &= ~UCB0RXIE; /* disable recive interrupt */
- IE2 |= UCB0TXIE; /* enable transmit interrupt */
- }
- void EEPROM_read_setup(void) {
- UCB0CTL1 &= ~UCTR; /* set recive mode */
- IFG2 &= ~UCB0RXIFG; /* clear recive interrupt flag */
- IE2 &= ~UCB0TXIE; /* disable transmit interrupt */
- IE2 |= UCB0RXIE; /* enable receive interrupt */
- }
- void EEPROM_ACK_polling(void) {
- while (UCB0STAT & UCBUSY); /* wait until I2C is free */
- UCB0CTL1 |= UCTR; /* set transmit mode */
- do {
- UCB0STAT &= ~UCNACKIFG; /* clear NACK flag */
- UCB0CTL1 |= UCTXSTT; /* send start message manually */
- while (UCB0CTL1 & UCTXSTT) { /* wait until start message sent */
- if (!(UCB0STAT & UCNACKIFG)) { /* break if ACK recived */
- break;
- }
- }
- UCB0CTL1 |= UCTXSTP; /* send stop message manually */
- while (UCB0CTL1 & UCTXSTP); /* wait until stop message sent */
- } while (UCB0STAT & UCNACKIFG); /* wait until ACK recived */
- }
- void EEPROM_sequential_read(unsigned char size, unsigned short addr, unsigned char *buffer) {
- while (UCB0STAT & UCBUSY); /* wait until I2C is free */
- i2c_buffer[1] = addr >> 8; /* save high byte */
- i2c_buffer[0] = addr & 0xFF; /* save low byte */
- ptr_buf = 1; /* set pointer */
- EEPROM_write_setup(); /* setup to write operation */
- UCB0CTL1 |= UCTXSTT; /* send start message manually */
- __bis_SR_register(LPM0_bits + GIE); /* enter interrupt w/ LP0 */
- EEPROM_read_setup(); /* setup to read operation */
- UCB0CTL1 |= UCTXSTT; /* send start message manually */
- while (UCB0CTL1 & UCTXSTT); /* wait until start message sent */
- /* read bytes excluding the last one */
- unsigned short cnt_size;
- for (cnt_size = 0 ; cnt_size < size - 1; cnt_size++) {
- __bis_SR_register(LPM0_bits + GIE); /* enter interrupt w/ LP0 */
- buffer[cnt_size] = i2c_buffer[0]; /* read byte */
- }
- /* send stop message and read last byte */
- UCB0CTL1 |= UCTXSTP; /* send stop message manually */
- __bis_SR_register(LPM0_bits + GIE); /* enter interrupt w/ LP0 */
- while (UCB0CTL1 & UCTXSTP); /* wait until stop message sent */
- buffer[cnt_size] = i2c_buffer[0]; /* read byte */
- }
- void EEPROM_page_write(unsigned char size, unsigned short addr, unsigned char *buffer, unsigned char ack) {
- while (UCB0STAT & UCBUSY); /* wait until I2C is free */
- i2c_buffer[size + 1] = addr >> 8; /* save high byte */
- i2c_buffer[size] = addr & 0xFF; /* save low byte */
- ptr_buf = size + 1; /* set pointer */
- unsigned short cnt_size;
- for (cnt_size = 0; cnt_size < size; cnt_size++) {
- i2c_buffer[size-cnt_size - 1] = buffer[cnt_size];
- }
- EEPROM_write_setup(); /* setup to write operation */
- UCB0CTL1 |= UCTXSTT; /* send start message manually */
- __bis_SR_register(LPM0_bits + GIE); /* enter interrupt w/ LP0 */
- UCB0CTL1 |= UCTXSTP; /* send stop message manually */
- while (UCB0CTL1 & UCTXSTP); /* wait until stop message sent */
- if (ack) {
- EEPROM_ACK_polling(); /* determine end data write cycle using ACK polling */
- } else {
- __delay_cycles(5000); /* wait 5ms (1 Mhz) */
- }
- }
- /*---- ISR ----*/
- #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
- #pragma vector = USCIAB0TX_VECTOR
- __interrupt void USCIAB0TX_I2C_ISR(void) {
- #elif defined(__GNUC__)
- void __attribute__ ((interrupt(USCIAB0TX_VECTOR))) USCIAB0TX_I2C_ISR (void) {
- #else
- #error Compiler not supported!
- #endif
- if (UCB0TXIFG & IFG2) {
- UCB0TXBUF = i2c_buffer[ptr_buf]; /* Load TX buffer */
- ptr_buf--; /* Decrement TX byte counter */
- if (ptr_buf < 0) {
- while (!(IFG2 & UCB0TXIFG));
- IE2 &= ~UCB0TXIE; /* disable interrupts */
- IFG2 &= ~UCB0TXIFG; /* Clear USCI_B0 TX int flag */
- __bic_SR_register_on_exit(LPM0_bits); /* Exit LPM0 */
- }
- } else if (UCB0RXIFG & IFG2) {
- i2c_buffer[0] = UCB0RXBUF; /* store received data in buffer */
- __bic_SR_register_on_exit(LPM0_bits); /* Exit LPM0 */
- }
- }
|