From 6b91cee738d21302507e294d23395d73b1dfe90f Mon Sep 17 00:00:00 2001 From: Shinichiro Nakamura Date: Fri, 10 Aug 2012 03:12:28 +0900 Subject: [PATCH] Separated the TWI codes. --- firm/bare_metal/Makefile | 2 +- firm/bare_metal/main.c | 224 +++++++++++++++-------------------------------- firm/bare_metal/twi.c | 74 ++++++++++++++++ firm/bare_metal/twi.h | 33 +++++++ 4 files changed, 180 insertions(+), 153 deletions(-) create mode 100644 firm/bare_metal/twi.c create mode 100644 firm/bare_metal/twi.h diff --git a/firm/bare_metal/Makefile b/firm/bare_metal/Makefile index 23dd611..ac35b81 100644 --- a/firm/bare_metal/Makefile +++ b/firm/bare_metal/Makefile @@ -6,7 +6,7 @@ PROJECT = bluetank # # Source files and search directories # -CSRC += lcd.c led.c main.c mmc.c pff.c +CSRC += lcd.c led.c main.c mmc.c pff.c twi.c ASRC += VPATH = diff --git a/firm/bare_metal/main.c b/firm/bare_metal/main.c index 67c2399..d64307d 100644 --- a/firm/bare_metal/main.c +++ b/firm/bare_metal/main.c @@ -1,23 +1,7 @@ -/* - * ACB-BF592 UMB-SSM2603 トークスルーコード例 - * - * Original : Copyright(C) 2012 Kaneko System Co., Ltd. - * - * Modified : Copyright(C) 2012 CuBeatSystems - * - Changed the SPORT port configuration to SPORT 0 from SPORT 1 - * - Changed the DMA for SPORT to DMA1 from DMA3. - * - Changed the DMA for SPORT to DMA2 from DMA4. - * - Added the control for the mute pin. - * - Modified interrupt function codes for gcc. - * The original code uses VisualDSP++. - * - * Last Update: 2012/07/07 - * - * 【ご注意】 - * ・どなたでも自由に改変して使用することができます。 - * ・このソフトウェアは無保証です。このファイルに記載されている情報・コードを - * 使用する場合は、ユーザの責任において行ってください。これらの使用に - * 起因し、ユーザまたは第三者に生じた損害に関し、当社は一切の責任を負いません。 +/** + * @file main.c + * @brief BlueTank ACB-BF592 Application Sample Codes. + * @author Copyright(C) 2012 Shinichiro Nakamura */ #include @@ -26,18 +10,11 @@ #include "lcd.h" #include "led.h" #include "pff.h" +#include "twi.h" /* システムクロック(100MHz) */ #define SCLOCK_HZ (100000000) -#define TWI_COUNT(x) (DCNT & ((x) << 6)) -/* TWI用戻り値 */ -#define NO_ERROR (0) -#define TWI_ERROR_NAK (-1) -/* s_twi_master_writeのrstart引数用定義 */ -#define TWI_STOP (0) -#define TWI_RSTART (1) - /* SSM2603のI2Cデバイスアドレス */ #define TWI_DEVICE_ADDR (0x1A) @@ -45,29 +22,23 @@ #define NUM_SAMPLES (256) /* SPORT RX DMA割り込みのプロトタイプ宣言 */ -void s_sport_rx_isr() __attribute__((interrupt_handler)); +void sport_rx_isr() __attribute__((interrupt_handler)); /* オーディオ処理用関数 */ -void s_audio_process(const int32_t* src, int32_t* des, int32_t count); - -/* TWI(I2C)初期化用関数 */ -void s_twi_init(void); -/* TWI(I2C)データ送信用関数 */ -int32_t s_twi_master_write(uint8_t slave_addr, int32_t rstart, const uint8_t* p_data, int32_t write_cnt); +void audio_effect(const int32_t* src, int32_t* des, int32_t count); /* SPORT受信バッファ(ダブルバッファ) */ -static int32_t sf_sport_rxbuf[2][NUM_SAMPLES]; +static int32_t sport_buffer_rx[2][NUM_SAMPLES]; /* SPORT受信バッファ(ダブルバッファ) */ -static int32_t sf_sport_txbuf[2][NUM_SAMPLES]; +static int32_t sport_buffer_tx[2][NUM_SAMPLES]; /* DMAがどのバッファ使用をしているか */ -static volatile int32_t sf_sport_use_bufidx; - +static volatile int32_t bufidx_dma_target; /* データ転送完了フラグ */ -static volatile int32_t sf_data_incoming; +static volatile int32_t data_ready; int iii; /* SSM2603 TWI初期化データ列 */ -static const uint8_t sf_audio_init_data[] = +static const uint8_t ssm2603_initdata[] = { (0x0F << 1) | 0, 0x00, (0x00 << 1) | 1, 0x17, @@ -82,7 +53,7 @@ static const uint8_t sf_audio_init_data[] = (0x09 << 1) | 0, 0x01, }; -static void s_bfin_clk_pll_set(uint8_t mul_val, uint8_t div_val) +static void setup_pll(uint8_t mul_val, uint8_t div_val) { *pSIC_IWR = IWR_ENABLE(0); /* PLLのみIWRを許す */ *pPLL_DIV = div_val; @@ -92,45 +63,48 @@ static void s_bfin_clk_pll_set(uint8_t mul_val, uint8_t div_val) } /* SPORT RX DMA割り込みハンドラ */ -__attribute__((interrupt_handler)) void s_sport_rx_isr() +__attribute__((interrupt_handler)) void sport_rx_isr() { *pDMA1_IRQ_STATUS = DMA_DONE; asm("ssync;"); /* オーディオコーデックからデータ到着 */ - sf_data_incoming = 1; + data_ready = 1; /* DMAが使用するバッファを変更 */ - sf_sport_use_bufidx = (sf_sport_use_bufidx ^ 1) & 1; + bufidx_dma_target = (bufidx_dma_target ^ 1) & 1; } int main(void) { - uint32_t l_lc, l_ld; - int32_t l_dmabuf_idx; + uint32_t i, j; + int32_t bufidx_dma_done; FATFS fatfs; DIR dir; FILINFO finfo; - /* PLLを設定 */ - s_bfin_clk_pll_set(16, 4); - - led_init(); + /* + * PLLを設定する。 + */ + setup_pll(16, 4); /* - * LED: Wait... + * LEDを初期化する。 */ + led_init(); led_write(LedTargetR, 1); led_write(LedTargetG, 0); + /* + * LCDを初期化する。 + */ lcd_init(); lcd_clear(); - lcd_goto(0, 0); lcd_puts("BlueTank"); lcd_goto(0, 1); lcd_puts("Init...."); /* - * PFF test + * SDカードをマウントする。 */ if (pf_mount(&fatfs) == FR_OK) { lcd_goto(0, 0); @@ -140,24 +114,34 @@ int main(void) lcd_puts("MT: FAIL"); } - /* バッファクリア */ - memset(sf_sport_rxbuf, 0 , sizeof(sf_sport_rxbuf)); - memset(sf_sport_txbuf, 0 , sizeof(sf_sport_txbuf)); - sf_sport_use_bufidx = 0; - sf_data_incoming = 0; + /* + * バッファをクリアする。 + */ + memset(sport_buffer_rx, 0 , sizeof(sport_buffer_rx)); + memset(sport_buffer_tx, 0 , sizeof(sport_buffer_tx)); + bufidx_dma_target = 0; + data_ready = 0; - /* ポートの設定 */ + /* + * ポートの設定 + */ *pPORTG_MUX &= ~(PG1 | PG2 | PG3 | PG5 | PG6 | PG7); *pPORTG_FER |= (PG1 | PG2 | PG3 | PG5 | PG6 | PG7); - /* TWI初期化 */ - s_twi_init(); - /* SSM2603初期化 */ - for (l_lc = 0; l_lc < sizeof(sf_audio_init_data); l_lc += 2) { - /* SSM2603レジスタ設定 */ - s_twi_master_write(TWI_DEVICE_ADDR, TWI_STOP, &sf_audio_init_data[l_lc], 2); - /* STOP CONDITIONから600ns以上空ける */ - for (l_ld = 0; l_ld < 300; l_ld++) { + /* + * TWI初期化 + */ + twi_init(); + + /* + * SSM2603初期化 + */ + for (i = 0; i < sizeof(ssm2603_initdata); i+=2) { + twi_master_write(TWI_DEVICE_ADDR, TWI_STOP, &ssm2603_initdata[i], 2); + /* + * STOP CONDITIONから600ns以上空ける + */ + for (j = 0; j < 300; j++) { asm("ssync;"); } } @@ -165,7 +149,7 @@ int main(void) /* * 割り込みハンドラをIVG9に登録 */ - *pEVT9 = s_sport_rx_isr; + *pEVT9 = sport_rx_isr; asm("ssync;"); asm volatile ("cli %0; bitset (%0, 9); sti %0; csync;": "+d"(iii)); // set IMASK bit asm("ssync;"); @@ -193,7 +177,7 @@ int main(void) */ *pDMA1_PERIPHERAL_MAP = 0x1000; *pDMA1_CONFIG = FLOW_AUTO | DI_EN | DI_SEL | DMA2D | WDSIZE_32 | WNR; - *pDMA1_START_ADDR = sf_sport_rxbuf; + *pDMA1_START_ADDR = sport_buffer_rx; *pDMA1_X_COUNT = NUM_SAMPLES; *pDMA1_X_MODIFY = sizeof(int32_t); *pDMA1_Y_COUNT = 2; @@ -204,7 +188,7 @@ int main(void) */ *pDMA2_PERIPHERAL_MAP = 0x2000; *pDMA2_CONFIG = FLOW_AUTO | DMA2D | WDSIZE_32; - *pDMA2_START_ADDR = sf_sport_txbuf; + *pDMA2_START_ADDR = sport_buffer_tx; *pDMA2_X_COUNT = NUM_SAMPLES; *pDMA2_X_MODIFY = sizeof(int32_t); *pDMA2_Y_COUNT = 2; @@ -226,33 +210,37 @@ int main(void) *pSPORT0_RCR1 |= RSPEN; asm("ssync;"); - lcd_goto(0, 1); - lcd_puts("InitDone"); - /* - * PG13(MUTE#)を出力ピンに設定します + * PG13(MUTE#)を出力ピンに設定する。 */ *pPORTGIO_DIR |= PG13; /* - * PG13(MUTE#)を'H'出力に設定します + * PG13(MUTE#)を'H'出力に設定する。 */ *pPORTGIO_SET = PG13; /* - * LED: Go! + * 初期化の完了をユーザに通知する。 */ led_write(LedTargetR, 0); led_write(LedTargetG, 1); + lcd_goto(0, 1); + lcd_puts("InitDone"); while (1) { asm("idle;"); - if (0 != sf_data_incoming) { - /* フラグクリア */ - sf_data_incoming = 0; - /* 使用してよいバッファを取得 */ - l_dmabuf_idx = sf_sport_use_bufidx ^ 1; - s_audio_process(sf_sport_rxbuf[l_dmabuf_idx], sf_sport_txbuf[l_dmabuf_idx], NUM_SAMPLES); + if (0 != data_ready) { + /* + * フラグをクリアする。 + */ + data_ready = 0; + + /* + * DMAが完了したバッファを使用してオーディオ処理を行なう。 + */ + bufidx_dma_done = bufidx_dma_target ^ 1; + audio_effect(sport_buffer_rx[bufidx_dma_done], sport_buffer_tx[bufidx_dma_done], NUM_SAMPLES); } } @@ -265,76 +253,8 @@ int main(void) * @param src 処理元バッファ。 * @param des 処理後バッファ。 */ -void s_audio_process(const int32_t *src, int32_t *des, int32_t count) +void audio_effect(const int32_t *src, int32_t *des, int32_t count) { memcpy(des, src, sizeof(int32_t) * count); } -/** - * @brief TWI(I2C)を初期化する。 - */ -void s_twi_init(void) -{ - *pTWI_CONTROL = 0; - asm("ssync;"); - *pTWI_CONTROL = TWI_ENA | 10U; - *pTWI_CLKDIV = CLKHI(50) | CLKLOW(50); - *pTWI_INT_MASK = RCVSERV | XMTSERV | MERR | MCOMP; - *pTWI_INT_STAT = *pTWI_INT_STAT; - *pTWI_FIFO_CTL = XMTFLUSH | RCVFLUSH; - asm("ssync;"); -} - -/** - * @brief TWI(I2C)バスに書き込む。 - * - * @param slave_addr スレーブアドレス。 - * @param rstart スタートコンディション。 - * @param p_data データ。 - * @param write_cnt 書き込むデータバイト数。 - * - * @retval NO_ERROR エラーなし。 - * @retval TWI_ERROR_NAK エラー。 - */ -int32_t s_twi_master_write(uint8_t slave_addr, int32_t rstart, const uint8_t* p_data, int32_t write_cnt) -{ - int32_t l_idx; - - if (write_cnt <= 0) { - return NO_ERROR; - } - - *pTWI_FIFO_CTL = 0; - *pTWI_INT_STAT = *pTWI_INT_STAT; - *pTWI_MASTER_STAT = BUFWRERR | BUFRDERR | LOSTARB | ANAK | DNAK; - *pTWI_MASTER_ADDR = slave_addr; - - /* - * Send first byte - */ - *pTWI_XMT_DATA8 = p_data[0]; - *pTWI_MASTER_CTL = TWI_COUNT(write_cnt) | MEN | (rstart ? RSTART : 0); - asm("ssync;"); - - for (l_idx = 1; l_idx < write_cnt; l_idx++) { - while(((*pTWI_INT_STAT & MERR) == 0U) && (*pTWI_FIFO_STAT == XMTSTAT)) { - asm("ssync;"); - } - *pTWI_XMT_DATA8 = p_data[l_idx]; - asm("ssync;"); - } - - /* - * 転送終了まで待機 - */ - while ((*pTWI_INT_STAT & MCOMP) == 0U) { - asm("ssync;"); - } - - if ((*pTWI_INT_STAT & MERR) == 0U) { - return NO_ERROR; - } else { - return TWI_ERROR_NAK; - } -} - diff --git a/firm/bare_metal/twi.c b/firm/bare_metal/twi.c new file mode 100644 index 0000000..9b07973 --- /dev/null +++ b/firm/bare_metal/twi.c @@ -0,0 +1,74 @@ + +#include "twi.h" +#include + +#define TWI_COUNT(x) (DCNT & ((x) << 6)) + +/** + * @brief TWI(I2C)を初期化する。 + */ +void twi_init(void) +{ + *pTWI_CONTROL = 0; + asm("ssync;"); + *pTWI_CONTROL = TWI_ENA | 10U; + *pTWI_CLKDIV = CLKHI(50) | CLKLOW(50); + *pTWI_INT_MASK = RCVSERV | XMTSERV | MERR | MCOMP; + *pTWI_INT_STAT = *pTWI_INT_STAT; + *pTWI_FIFO_CTL = XMTFLUSH | RCVFLUSH; + asm("ssync;"); +} + +/** + * @brief TWI(I2C)バスに書き込む。 + * + * @param slave_addr スレーブアドレス。 + * @param rstart スタートコンディション。 + * @param p_data データ。 + * @param write_cnt 書き込むデータバイト数。 + * + * @retval NO_ERROR エラーなし。 + * @retval TWI_ERROR_NAK エラー。 + */ +int32_t twi_master_write(uint8_t slave_addr, int32_t rstart, const uint8_t* p_data, int32_t write_cnt) +{ + int32_t l_idx; + + if (write_cnt <= 0) { + return NO_ERROR; + } + + *pTWI_FIFO_CTL = 0; + *pTWI_INT_STAT = *pTWI_INT_STAT; + *pTWI_MASTER_STAT = BUFWRERR | BUFRDERR | LOSTARB | ANAK | DNAK; + *pTWI_MASTER_ADDR = slave_addr; + + /* + * Send first byte + */ + *pTWI_XMT_DATA8 = p_data[0]; + *pTWI_MASTER_CTL = TWI_COUNT(write_cnt) | MEN | (rstart ? RSTART : 0); + asm("ssync;"); + + for (l_idx = 1; l_idx < write_cnt; l_idx++) { + while(((*pTWI_INT_STAT & MERR) == 0U) && (*pTWI_FIFO_STAT == XMTSTAT)) { + asm("ssync;"); + } + *pTWI_XMT_DATA8 = p_data[l_idx]; + asm("ssync;"); + } + + /* + * 転送終了まで待機 + */ + while ((*pTWI_INT_STAT & MCOMP) == 0U) { + asm("ssync;"); + } + + if ((*pTWI_INT_STAT & MERR) == 0U) { + return NO_ERROR; + } else { + return TWI_ERROR_NAK; + } +} + diff --git a/firm/bare_metal/twi.h b/firm/bare_metal/twi.h new file mode 100644 index 0000000..8c61466 --- /dev/null +++ b/firm/bare_metal/twi.h @@ -0,0 +1,33 @@ +#ifndef TWI_H +#define TWI_H + +#include + +/* TWI用戻り値 */ +#define NO_ERROR (0) +#define TWI_ERROR_NAK (-1) + +/* twi_master_writeのrstart引数用定義 */ +#define TWI_STOP (0) +#define TWI_RSTART (1) + +/** + * @brief TWI(I2C)を初期化する。 + */ +void twi_init(void); + +/** + * @brief TWI(I2C)バスに書き込む。 + * + * @param slave_addr スレーブアドレス。 + * @param rstart スタートコンディション。 + * @param p_data データ。 + * @param write_cnt 書き込むデータバイト数。 + * + * @retval NO_ERROR エラーなし。 + * @retval TWI_ERROR_NAK エラー。 + */ +int32_t twi_master_write(uint8_t slave_addr, int32_t rstart, const uint8_t* p_data, int32_t write_cnt); + +#endif + -- 2.11.0