2016年6月6日月曜日

NucleoシーケンサーとPSoC4 DCOのテスト(その2)

PSoC4 DCOの波形が崩れる原因を追い込んでみたが、まだはっきりわからない。

SPIの受信をメインループ内でポーリングしていたのを、SPI(SCB)コンポーネントのInterruput SourceでFIFOにデータが5エントリー溜まったら割り込みが発生するようにして処理してみた。


main.c

/* ========================================
 *
 * Copyright YOUR COMPANY, THE YEAR
 * All Rights Reserved
 * UNPUBLISHED, LICENSED SOFTWARE.
 *
 * CONFIDENTIAL AND PROPRIETARY INFORMATION
 * WHICH IS THE PROPERTY OF your company.
 *
 * ========================================
*/
#include <project.h>
#include <stdio.h>

#define UART_TRACE  (0)
#define LCD_DISPLAY (0)

#define TITLE_STR1  ("PSoC 4 DCO")
#define TITLE_STR2  ("20160606")

#define SAMPLING_CLOCK           (24000000)
#define SPIS_RX_PACKET_SIZE      (5)
#define SPIS_RX_PACKET_HEADER    (0x55)

#define WAVESHAPE_SQUARE    0
#define WAVESHAPE_SAW       1
#define WAVESHAPE_N         2

volatile uint8 count;

uint8 waveShape   = WAVESHAPE_SQUARE;
uint8 squareDuty  = 127;
int32 frequency10 = 4400;

#if(LCD_DISPLAY)
void printLCD(uint8* rxBuffer)
{
    char strBuffer[20];
    sprintf(strBuffer, "%3u %3u %3u %3u",
    rxBuffer[0], rxBuffer[1], rxBuffer[2], rxBuffer[3]);
    LCD_Char_Position(0, 0);
    LCD_Char_PrintString(strBuffer);
    sprintf(strBuffer, "%3u %5ld", rxBuffer[4], frequency10);
    LCD_Char_Position(1, 0);
    LCD_Char_PrintString(strBuffer);
}
#endif

CY_ISR(ISR_Saw_handler)
{
    Pin_Check2_Write(1);
    
    count++;
    IDAC8_SetValue(count);
 
    Timer_Sampling_ClearInterrupt(Timer_Sampling_INTR_MASK_TC);
    
    Pin_Check2_Write(0);
}

CY_ISR(ISR_Square_handler)
{
    Pin_Check2_Write(1);
    
    count++;
    IDAC8_SetValue((count / squareDuty) ? 255 : 0);    
    
    Timer_Sampling_ClearInterrupt(Timer_Sampling_INTR_MASK_TC);

    Pin_Check2_Write(0);    
}

void doCommand(uint8 *rxBuffer)
{
    uint16 timerPeriod;
    
    if (waveShape != rxBuffer[1]) {
        waveShape = rxBuffer[1];
        switch (waveShape) {
        case WAVESHAPE_SQUARE:
            ISR_Timer_Sampling_StartEx(ISR_Square_handler);
            break;
        case WAVESHAPE_SAW:
            ISR_Timer_Sampling_StartEx(ISR_Saw_handler);
            break;
        }
    }

    squareDuty = rxBuffer[2];
    frequency10 = ((uint16)rxBuffer[3] << 8) | rxBuffer[4];
    
    timerPeriod = (uint64)SAMPLING_CLOCK * 10 / (frequency10 * 256);
    Timer_Sampling_WritePeriod(timerPeriod);
}

void SPI_RX_handler()
{
    uint8 rxBuffer[SPIS_RX_PACKET_SIZE];
    int i;
    
    Pin_Check1_Write(1);
    
    rxBuffer[0] = SPIS_SpiUartReadRxData();
    if (SPIS_RX_PACKET_HEADER == rxBuffer[0]) {
        for (i = 1; i < SPIS_RX_PACKET_SIZE; i++) {
            rxBuffer[i] = SPIS_SpiUartReadRxData();
        }
        doCommand(rxBuffer);
    }
    
    SPIS_ClearRxInterruptSource(SPIS_INTR_RX_FIFO_LEVEL);
    
    Pin_Check1_Write(0);
}

int main()
{
    CyGlobalIntEnable; /* Enable global interrupts. */

    #if(UART_TRACE)
    UART_Start();
    UART_UartPutString("PSoC 4 SPI Slave Test\r\n");
    #endif
    
    #if(LCD_DISPLAY)
    LCD_Char_Start();
    LCD_Char_ClearDisplay();
    LCD_Char_PrintString(TITLE_STR1);
    LCD_Char_Position(1, 0);
    LCD_Char_PrintString(TITLE_STR2);
    CyDelay(1000);
    #endif
    
    IDAC8_Start();
    Opamp_IV_Conv_Start();

    Timer_Sampling_Start();
    ISR_Timer_Sampling_StartEx(ISR_Saw_handler);
    
    SPIS_SetCustomInterruptHandler(SPI_RX_handler);
    SPIS_Start();

    for(;;)
    {
    }
}

/* [] END OF FILE */

SPI信号とタイマー割り込み


割り込みがかからない?

ch1:Pin_Check1 ch2:SPI_MOSI

拡大

ch1のPin_Check1はタイマー割り込みがかかるたびに割り込み処理ルーチンの最初と最後でH→Lさせている。

ch2はSPIのMOSIの信号を拾っている。1枚目の画像はch2が単にH→Lになっているように見えるが、拡大するとHの後にMOSIの信号が流れて最後はLになっている。MOSIの通信の前後のレベルは不定でよいと思うのでHでもLでもいいと思うけど、違うかな?

SPIのマスター(Nucleo)から音程が変更されるデータが送られてくるタイミングで、1枚目の画像のようにゴソッと割り込みがかからなくなる。

出力波形をWaveSpectraで取り込み

メモ:


いくつかバグや無駄な処理があったので修正してみたが、改善されない。

DWRエディターでSPIとタイマーの割り込みの優先度を変えてみたがかえって悪化する(ーー;

SPIとタイマー割り込みの絡みかと思っていたが、周期的に割り込みが発生している最中にPeriod(割り込みの周期)を変更しているのが原因のような気もする。

→SPIの処理を外して実験して見る。

mbed erepository:
https://developer.mbed.org/users/ryood/code/SpiSequenceSender_Test/

Github:
https://github.com/ryood/PSoC4_DCO/tree/master/PSoC/PSoC4_DCO_for_NucleoF401RE_Interrupt_Test.cydsn