diff --git a/lib/l_test.c b/lib/l_test.c index 79b7120..470ba13 100644 --- a/lib/l_test.c +++ b/lib/l_test.c @@ -57,6 +57,12 @@ static int l_tp_jack_direction(lua_State* L){ return 0; } +static int l_tp_dac(lua_State* L){ + TP_dac( luaL_checkinteger(L, 1), luaL_checknumber(L, 2) ); + lua_settop(L, 0); + return 0; +} + // array of all the available functions static const struct luaL_Reg lib_test[]= { { "tp_power12" , l_tp_power12 } @@ -68,6 +74,7 @@ static const struct luaL_Reg lib_test[]= , { "tp_dacmux1" , l_tp_dac_mux_1 } , { "tp_dacmux2" , l_tp_dac_mux_2 } , { "tp_jack_dir" , l_tp_jack_direction} + , { "tp_dac" , l_tp_dac } , { NULL , NULL } }; diff --git a/ll/dac108.c b/ll/dac108.c index f62a2d2..21968c4 100644 --- a/ll/dac108.c +++ b/ll/dac108.c @@ -21,9 +21,11 @@ float dac_calibrated_scalar[DAC_CHANNELSS]; static void sai_start_transmit(uint16_t* hwords, uint16_t count); static void sai_init(void); +static void sai_init_directmode(void); void DAC_Init(uint16_t bsize, uint8_t chan_count){ - sai_init(); + // sai_init(); + sai_init_directmode(); // Create the sample buffer for DMA transfer samp_count = DAC_BUFFER_COUNT * bsize * chan_count; // 512 @@ -48,7 +50,7 @@ void DAC_Start(void){ samples[i] = chan_mod<<12; // sets channel select bits } } - sai_start_transmit(samples, samp_count); + // sai_start_transmit(samples, samp_count); } void DAC_CalibrateScalar( uint8_t channel, float scale ){ @@ -133,6 +135,58 @@ static void sai_init(void){ hsai_a.Init.FirstBit = SAI_FIRSTBIT_MSB; hsai_a.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; // CONFIRM + hsai_a.FrameInit.FrameLength = 17; // ie data length plus 1 bit for FS sync pulse + hsai_a.FrameInit.ActiveFrameLength = 1; + hsai_a.FrameInit.FSDefinition = SAI_FS_STARTFRAME; + hsai_a.FrameInit.FSPolarity = SAI_FS_ACTIVE_HIGH; + hsai_a.FrameInit.FSOffset = SAI_FS_BEFOREFIRSTBIT; + + hsai_a.SlotInit.FirstBitOffset = 0; // maybe 1? + hsai_a.SlotInit.SlotSize = SAI_SLOTSIZE_16B; + hsai_a.SlotInit.SlotNumber = 1; // ie. only 1 chip in sequence + hsai_a.SlotInit.SlotActive = SAI_SLOTACTIVE_0; // each DAC chan needs it's own frame! + + if(HAL_SAI_Init(&hsai_a)){ + printf("sai init failed\n\r"); + return; + } + + // Enable SAI to generate clock used by audio driver + __HAL_SAI_ENABLE(&hsai_a); +} + +static void sai_init_directmode(void){ + RCC_PeriphCLKInitTypeDef rcc; + rcc.PeriphClockSelection = RCC_PERIPHCLK_SAI1; + rcc.Sai1ClockSelection = RCC_SAI1CLKSOURCE_PLLSAI; + + // here we configure for 3.072MHz + // ie 8 channels, 16bits, 24kHz sample rate + rcc.PLLSAI.PLLSAIN = 384; + rcc.PLLSAI.PLLSAIQ = 5; + rcc.PLLSAIDivQ = 25; + // see @ciel/tools/sai_pll_calculator.lua to configure + + HAL_RCCEx_PeriphCLKConfig(&rcc); + + // Initialize SAI + __HAL_SAI_RESET_HANDLE_STATE(&hsai_a); + + // block A + hsai_a.Instance = SAI1_Block_A; // TODO follow instance + __HAL_SAI_DISABLE(&hsai_a); + hsai_a.Init.AudioMode = SAI_MODEMASTER_TX; + hsai_a.Init.Synchro = SAI_ASYNCHRONOUS; + hsai_a.Init.SynchroExt = SAI_SYNCEXT_DISABLE; + hsai_a.Init.OutputDrive = SAI_OUTPUTDRIVE_ENABLE; + hsai_a.Init.NoDivider = SAI_MASTERDIVIDER_DISABLE; + hsai_a.Init.FIFOThreshold = SAI_FIFOTHRESHOLD_1QF; + hsai_a.Init.AudioFrequency = SAI_AUDIO_FREQUENCY_48K; // _48K or _96K or _192K + hsai_a.Init.Protocol = SAI_FREE_PROTOCOL; + hsai_a.Init.DataSize = SAI_DATASIZE_16; + hsai_a.Init.FirstBit = SAI_FIRSTBIT_MSB; + hsai_a.Init.ClockStrobing = SAI_CLOCKSTROBING_RISINGEDGE; // CONFIRM + hsai_a.FrameInit.FrameLength = 17; // was 33 for 32 vals hsai_a.FrameInit.ActiveFrameLength = 1; // 1 ? hsai_a.FrameInit.FSDefinition = SAI_FS_STARTFRAME; @@ -141,11 +195,8 @@ static void sai_init(void){ hsai_a.SlotInit.FirstBitOffset = 0; hsai_a.SlotInit.SlotSize = SAI_SLOTSIZE_16B; - hsai_a.SlotInit.SlotNumber = 8; - hsai_a.SlotInit.SlotActive = SAI_SLOTACTIVE_0 | SAI_SLOTACTIVE_1 - | SAI_SLOTACTIVE_2 | SAI_SLOTACTIVE_3 - | SAI_SLOTACTIVE_4 | SAI_SLOTACTIVE_5 - | SAI_SLOTACTIVE_6 | SAI_SLOTACTIVE_7; + hsai_a.SlotInit.SlotNumber = 1; + hsai_a.SlotInit.SlotActive = SAI_SLOTACTIVE_0; if(HAL_SAI_Init(&hsai_a)){ printf("sai init failed\n\r"); @@ -163,7 +214,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) GPIO_Init.Pull = GPIO_PULLUP; GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH; - __HAL_RCC_DMA2_CLK_ENABLE(); + // __HAL_RCC_DMA2_CLK_ENABLE(); __HAL_RCC_SAI1_CLK_ENABLE(); // RCC __HAL_RCC_GPIOE_CLK_ENABLE(); GPIO_Init.Alternate = GPIO_AF6_SAI1; @@ -178,6 +229,7 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) // Configure DMA used for SAI1_A // d2.s3.c0 // alternates: 2.1.0, 2.3.0, 2.6.10 + /* hdma_tx_a.Init.Channel = DMA_CHANNEL_0; hdma_tx_a.Init.Direction = DMA_MEMORY_TO_PERIPH; hdma_tx_a.Init.PeriphInc = DMA_PINC_DISABLE; @@ -211,12 +263,13 @@ void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai) , 1 ); HAL_NVIC_EnableIRQ( DMA2_Stream3_IRQn ); + */ } void sai_start_transmit(uint16_t* hwords, uint16_t count){ - if(HAL_SAI_Transmit_DMA(&hsai_a, (uint8_t*)hwords, count)){ - printf("sai transmit fail.\n\r"); - } + // if(HAL_SAI_Transmit_DMA(&hsai_a, (uint8_t*)hwords, count)){ + // printf("sai transmit fail.\n\r"); + // } } @@ -258,3 +311,23 @@ void HAL_SAI_ErrorCallback(SAI_HandleTypeDef *hsai){ printf("sai error 0x%x\n\r", hsai->ErrorCode); } +static const uint16_t write_through_mode = 0b1001000000000000; +static uint16_t dac_data = 0; +void dac108_immediatemode(void){ + dac_data = write_through_mode; + if( HAL_OK != HAL_SAI_Transmit(&hsai_a, (uint8_t*)&dac_data, 1, 0x100) ){ + printf("imm mode fail\n\r"); + } +} + +// channel is 0-7 +// float is 0.0 ~ 1.0 (maps to full range depending on output) +void dac108_send(int channel, float val){ + dac_data = (channel&7) << 12; + val += 1.0; // 0 ~ 2 + val *= 2047.0; // 0 ~ 4095 (12bits) + dac_data |= ((uint16_t)val) & 0xFFF; + if( HAL_OK != HAL_SAI_Transmit(&hsai_a, (uint8_t*)&dac_data, 1, 0x100) ){ + printf("dac send fail\n\r"); + } +} diff --git a/ll/dac108.h b/ll/dac108.h index 507b317..c09f0a1 100644 --- a/ll/dac108.h +++ b/ll/dac108.h @@ -13,10 +13,11 @@ void DAC_PickleBlock( uint16_t* dac_pickle_ptr , uint16_t bsize ); -void DAC_I2S_MspInit(I2S_HandleTypeDef *hi2s); -void DAC_I2S_MspDeInit(I2S_HandleTypeDef *hi2s); - - +// direct mode output +// channel is 0-7 +// float is -1.0 ~ 1.0 (maps to full range depending on output) +void dac108_immediatemode(void); +void dac108_send(int channel, float val); // new void HAL_SAI_MspInit(SAI_HandleTypeDef *hsai); diff --git a/ll/tp.c b/ll/tp.c index a0d5fc1..12e3c5a 100644 --- a/ll/tp.c +++ b/ll/tp.c @@ -266,3 +266,8 @@ void TP_adc_mux_1(int chan){ HAL_GPIO_WritePin(GPIOD, GPIO_PIN_6, (chan & 0b100)>>2); } } + +#include "dac108.h" +void TP_dac(int chan, float value){ + dac108_send(chan-1, value); +} diff --git a/ll/tp.h b/ll/tp.h index 459eed5..b7ca65c 100644 --- a/ll/tp.h +++ b/ll/tp.h @@ -17,6 +17,8 @@ void TP_jack_direction(int select); void TP_adc_mux_1(int chan); // controlled by ADC driver +void TP_dac(int chan, float value); + ///////////////////////////////// // read on demand diff --git a/main.c b/main.c index 92044c8..a4b2c08 100755 --- a/main.c +++ b/main.c @@ -20,6 +20,7 @@ #include "stm32f7xx_it.h" // CPU_count; #include "ll/tp.h" // test platform specifics +#include "ll/dac108.h" int main(void) @@ -42,7 +43,12 @@ int main(void) // Drivers int max_timers = Timer_Init(); IO_Init( max_timers-2 ); // use second-last timer - IO_Start(); // must start IO before running lua init() script + +// NOTE: can't get DAC working on DMA, so just using direct-mode w fn-calls +// will need to fix this when we get to frequency-counting & signal generation +// but not required until working on TS. + // IO_Start(); // must start IO before running lua init() script + events_init(); Metro_Init( max_timers-2 ); // reserve 2 timers for USB & ADC clock_init( 100 ); // TODO how to pass it the timer? @@ -61,6 +67,9 @@ int main(void) REPL_print_script_name(); Lua_crowbegin(); + dac108_immediatemode(); // tell DAC to immediately update outputs on received data + + uint32_t last_tick = HAL_GetTick(); int a = 0; while(1){