もっと今更、SC-88ProにS/PDIFを付けよう
もっと今更、SC-88ProにS/PDIFを付けよう
STM32F103C8T6 ARM STM32 (blue pill)
- モデル:STM32F103C8T6
- コア:ARM 32 Cortex-M3 CPU
- 72MHz頻度を作動させる
- 64Kフラッシュメモリ、20K SRAM
- 2.0-3.6Vパワー、I/O
というやつ。
詳細はwikiの説明に
https://developer.mbed.org/users/peu605/code/DIT88proSTM32F1/wiki/説明
しまったなぁ、wikiのタイトル、漢字にしてしまったよ…
STM32F103C8T6, Roland, SC-88pro, S/PDIF, SPIDF, デジタル出力
Diff: main.cpp
- Revision:
- 2:62c8aa0c38c7
- Parent:
- 1:d7c7d1651f2e
- Child:
- 3:bdac1803f0fd
--- a/main.cpp Sat Sep 02 14:49:27 2017 +0000 +++ b/main.cpp Mon Sep 04 16:54:24 2017 +0000 @@ -1,5 +1,6 @@ #include "dit88prostm32.h" -//#include "mbed.h" +#include "mbed.h" + /** * STM32F103C8T6 Blue Pill, Low Layer drivers test @@ -32,11 +33,11 @@ // serial audio data length #define SDATA_LENGH 18 -#define MAX_SPI_DELAY 12 // 32 - 19 - 1 -#define MASK31_19 0xfff80000 +#define MAX_SPI_DELAY 13 // 32 - 18 -1 +#define MASK31_20 0xfff00000 +#define MASK23_0 0x00ffffff -#define _LED_LOAD -//#define _LED_SPI_DELAY +//#define _DEBUG_CONSOLE // SPI-DMA buffers @@ -70,10 +71,11 @@ int main() { - + SystemClock_Config(); + setupPeripherals(); setChannelStatus(); - + HAL_Delay(1000); // enable SPI and deselect @@ -93,15 +95,8 @@ // wait for interrupt while (true) { -#ifdef _LED_SPI_DELAY - // measured spiDelay is 3. - for (uint32_t i = 0; i < spiDelay; ++i) { - _LED_ON(); - HAL_Delay(250); - _LED_OFF(); - HAL_Delay(250); - } - HAL_Delay(1000); +#ifdef _DEBUG_CONSOLE + debugOut(); #endif __WFI(); @@ -112,18 +107,15 @@ void transferFrames() { -#ifdef _LED_LOAD // measured load is 20.8% _LED_OFF(); // PC_13 to HIGH -#endif for (uint32_t i = 0; i < BUFFER_NUM_FRAMES / 2; ++i) { transferFrame(); } -#ifdef _LED_LOAD _LED_ON(); // PC_13 to LOW -#endif + } @@ -166,30 +158,32 @@ // ====================================== // Roland SC-88pro, 256fs, 18bit right justified, MSB first - // SC-88pro's output format might be 2's complement 18 bit audio data in 19 bit data frame. + // SC-88pro's output format seems to be 2's complement 18 bit audio data in 20 bit data frame. // // SPIRxBuff, each channel data have 128(=256/2) bits, M:MSB, L:LSB + // 127 <--- ---> 0 + // 0000 ... 0000000 00000000000M==== ===============L + // 1111 ... 1111111 11111111111M==== ===============L + // ---- ... ------- ---------------- ---------------- // +0 -> 5 hlf_word +6 +7 - // 0000 ... 0000000 0000000000000MM= ===============L - // 1111 ... 1111111 1111111111111MM= ===============L - // ---- ... ------- ---------------- ---------------- // 1111 ... 0000000 1111110000000000 1111110000000000 // 5432 6543210 5432109876543210 5432109876543210 // // Actually, SPI starts some SCKs after LRCK change. // Received data are shifted leftward. // - // +0 -> 5 hlf_word +6 +7 |<->| spiDelay - // MM====== ==========L + // 127 <--- ---> 0 + // |<->| spiDelay + // M========= ==========L // ---- ... ------- ---------------- ---------------- + // +0 -> 5 hlf_word +6 +7 // 1111 ... 0000000 1111110000000000 1111110000000000 // 5432 6543210 5432109876543210 5432109876543210 // - // bit[127:19] is all 0 or all 1. + // bit[127:20] is all 0 or all 1. // - // bit[31:19] should be 000...00 or 111...11 - // bit[18] same as MSB bit - // bit[17:0] audio data, MSB to LSB + // bit[31:20] should be 000...00 or 111...11 + // bit[19:0] MSB to LSB, 2's complement 18 bit audio data in 20 bit data frame // arithmetic right shift int32_t val = (*(rxBuffPtr + 6) << 16) | *(rxBuffPtr + 7); @@ -197,8 +191,8 @@ // determine spiDelay while(true) { - int32_t test = val & MASK31_19; - if (test == 0 || test == MASK31_19) { + int32_t test = val & MASK31_20; + if (test == 0 || test == MASK31_20) { break; } else { if (spiDelay == MAX_SPI_DELAY) { @@ -221,7 +215,7 @@ // So, V position is (28 - 4), C pos is (30 - 4), and P pos is (31 - 4). // mask with 24 bit to clear VUCP bits - val &= 0x00ffffff; + val &= MASK23_0; // set Channel status bit uint32_t bitPos = frameIndex & 7; @@ -244,7 +238,7 @@ // Z:preamble, A:aux, L:LSB, M:MSB, 0:filler(unused bit) // V:validity, U:user, C:ch status, P:parity - // ===> LSB to MSB, right to left + // ===> BMC encode from LSB to MSB //(PCUVM================L00AAAAZZZZ) // PCUVM================L00AAAA w/o preamble (= val) // -------------------------------- @@ -254,14 +248,14 @@ // Write Biphase Mark Code data to SPITx-DMA buffer // First, 0 ~ 4 bit is Preamble. Not BMC! uint16_t bmc; - if (frameIndex == 0 && aCh) { + if (!aCh) { + bmc = lastCellZero ? PREAMBLE_Y : ~PREAMBLE_Y; + } else if (frameIndex == 0) { bmc = lastCellZero ? PREAMBLE_Z : ~PREAMBLE_Z; - } else if (aCh) { + } else { bmc = lastCellZero ? PREAMBLE_X : ~PREAMBLE_X; - } else { - bmc = lastCellZero ? PREAMBLE_Y : ~PREAMBLE_Y; } - lastCellZero = (bmc & 1) == 0; + lastCellZero = !(bmc & 1); //lastCellZero = (bmc & 1) == 0; *txBuffPtr++ = bmc; // Next, 5 ~ 31 bit, audio data and VUCP bits. 28/4 = 7 loops @@ -269,7 +263,7 @@ for (uint32_t i = 0; i < 7 ; ++i) { bmc = lastCellZero ? bmcTable[val & 0x0f] : ~bmcTable[val & 0x0f]; - lastCellZero = (bmc & 1) == 0; + lastCellZero = !(bmc & 1); *txBuffPtr++ = bmc; val >>= 4; } @@ -339,8 +333,98 @@ } +void toBinary(uint16_t *val_ptr, char *str) +{ + uint16_t val = *val_ptr; + for (uint32_t j = 0; j < 16; ++j) { + *str = val & 0x8000 ? '1' : '0'; + val <<= 1; + ++str; + } + *str = '\0'; +} + +#ifdef _DEBUG_CONSOLE +uint16_t tmpData[8]; +char str[17]; +Serial pc(PA_2, PA_3); + +void debugOut() +{ +// pc.printf("SystemCoreClock =%d\n", SystemCoreClock); + + for (uint8_t i = 6; i < 8; ++i) { + tmpData[i] = spiRxBuff[0].ltCh[i]; + } + pc.printf("Delay:%02d", spiDelay); + for (uint8_t i = 6; i < 8; ++i) { + pc.printf(" "); + toBinary(&tmpData[i], (char*) &str); + pc.printf(str); + } + pc.printf("\n"); + HAL_Delay(200); +} +#endif + +/** + * @brief System Clock Configuration + * The system Clock is configured as follow : + * System Clock source = PLL (HSE) + * SYSCLK(Hz) = 72000000 + * HCLK(Hz) = 72000000 + * AHB Prescaler = 1 + * APB1 Prescaler = 2 + * APB2 Prescaler = 1 + * HSE Frequency(Hz) = 8000000 + * PLLMUL = 9 + * Flash Latency(WS) = 2 + * @param None + * @retval None + */ +void SystemClock_Config(void) +{ + + /* Set FLASH latency */ + LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); + + /* Enable HSE oscillator */ +// LL_RCC_HSE_EnableBypass(); + LL_RCC_HSE_Enable(); + while(LL_RCC_HSE_IsReady() != 1) { + }; + + /* Main PLL configuration and activation */ + LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE_DIV_1, LL_RCC_PLL_MUL_9); + + LL_RCC_PLL_Enable(); + while(LL_RCC_PLL_IsReady() != 1) { + }; + + /* Sysclk activation on the main PLL */ + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); + while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) { + }; + + /* Set APB1 & APB2 prescaler*/ + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + /* Set systick to 1ms in using frequency set to 72MHz */ + LL_Init1msTick(72000000); + + /* Update CMSIS variable (which can be updated also through SystemCoreClockUpdate function) */ + LL_SetSystemCoreClock(72000000); + + // 本当に72MHzかなぁ… + +} + + void setupPeripherals() { + // enable GPIOB/C clock LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB); LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC); @@ -416,7 +500,4 @@ LL_DMA_EnableChannel(_SPIRxDMA, _SPIRxDMACh); LL_DMA_EnableChannel(_SPITxDMA, _SPITxDMACh); - // sleep - LL_LPM_EnableSleep(); - }