/* * si4703.c * * Created on: Aug 1, 2023 * Author: User */ #include "main.h" #include "i2c.h" #include "tim.h" #include "usart.h" #include "gpio.h" #include "si4703.h" #define Si4703_SC2_BAND0 6 // Band select #define Si4703_SC2_BAND1 7 uint16_t si4703_registers[16]={0,}; void SI4703setVolume(int8_t newVolume) { if (newVolume > 15) { newVolume = 15; } readsi4703_registers(); // Read the current register set si4703_registers[SYSCONFIG2] &= ~(VOLUME_MASK); // Clear volume bits si4703_registers[SYSCONFIG2] |= newVolume; // Set new volume savesi4703_registers(); // Update } // Mono / Stereo void SI4703setMono(_Bool switchOn) { readsi4703_registers(); // Read the current register set if(switchOn) { si4703_registers[POWERCFG] |= (1 << SETMONO); // set force mono bit } else { si4703_registers[POWERCFG] &= ~(1 << SETMONO); // clear force mono bit } // if savesi4703_registers(); } // setMono /// Switch mute mode. void SI4703setMute(_Bool switchOn) { readsi4703_registers(); // Read the current register set if(switchOn) { si4703_registers[POWERCFG] &= ~(1 << DMUTE); // clear mute bit } else { si4703_registers[POWERCFG] |= (1 << DMUTE); // set mute bit } // if savesi4703_registers(); } // setMute() /// Switch soft mute mode. void SI4703setSoftMute(_Bool switchOn) { readsi4703_registers(); // Read the current register set if(switchOn) { si4703_registers[POWERCFG] &= ~(1 << DSMUTE); // clear mute bit } else { si4703_registers[POWERCFG] |= (1 << DSMUTE); // set mute bit } // if savesi4703_registers(); } // setSoftMute() void SI4703setBand(void) { readsi4703_registers(); // Read the current register set // PowerConfig si4703_registers[POWERCFG] = 0x4001; // Enable the IC si4703_registers[POWERCFG] |= (1 << DMUTE); // disable Mute si4703_registers[POWERCFG] |= (1 << DSMUTE); // disable softmute si4703_registers[SYSCONFIG1] |= (1 << RDS); // Enable RDS si4703_registers[SYSCONFIG1] |= DEEMPHASIS50; // 50µs si4703_registers[SYSCONFIG2] &= ~(FMSPACE_MASK); // Clear all si4703_registers[SYSCONFIG2] |= FMSPACE_100; // set 100 si4703_registers[SYSCONFIG2] &= ~(VOLUME_MASK); si4703_registers[SYSCONFIG2] |= (1 & VOLUME_MASK); // Set volume // set seek parameters si4703_registers[SYSCONFIG2] |= SEEKTH_MID; // Set volume si4703_registers[SYSCONFIG3] &= ~(SKSNR_MASK); // Clear seek mask bits si4703_registers[SYSCONFIG3] |= SKSNR_MID; // Set volume si4703_registers[POWERCFG] |= (1 << RDSMODE); // set force verbose bit savesi4703_registers(); // Update delay_ms(110); // Max powerup time, from datasheet page 13 // if } // setBand() uint16_t SI4703getFrequency(void) { readsi4703_registers(); uint16_t channel = si4703_registers[READCHAN] & 0x03FF; uint16_t _freq = (channel * 10)+ 8700; return (_freq); } void SI4703setFrequency(uint16_t newF) { if (newF < 8700) newF = 8700; if (newF > 10800) newF = 10800; readsi4703_registers(); int channel = (newF - 8700) / 10; // These steps come from AN230 page 20 rev 0.5 si4703_registers[CHANNEL] &= 0xFE00; // Clear out the channel bits si4703_registers[CHANNEL] |= channel; // Mask in the new channel si4703_registers[CHANNEL] |= (1 << TUNE); // Set the TUNE bit to start savesi4703_registers(); SI4703waitEnd(); } // setFrequency() void SI4703seek(_Bool seekUp) { uint16_t reg; readsi4703_registers(); // not wrapping around. reg = si4703_registers[POWERCFG] & ~((1 << SKMODE) | (1 << SEEKUP)); if (seekUp) reg |= (1 << SEEKUP); // Set the Seek-up bit reg |= (1 << SEEK); // Start seek now // save the registers and start seeking... si4703_registers[POWERCFG] = reg; savesi4703_registers(); SI4703waitEnd(); } // _seek void SI4703waitEnd(void) { // wait until STC gets high do { SI4703_readRegister0A(); delay_ms(10); } while ((si4703_registers[STATUSRSSI] & STC) == 0); // DEBUG_VAL("Freq:", getFrequency()); readsi4703_registers(); // get the SFBL bit. if (si4703_registers[STATUSRSSI] & SFBL) { } //DEBUG_STR("Seek limit hit"); // end the seek mode si4703_registers[POWERCFG] &= ~(1 << SEEK); si4703_registers[CHANNEL] &= ~(1 << TUNE); // Clear the tune after a tune has completed savesi4703_registers(); // wait until STC gets down again do { readsi4703_registers(); }while ((si4703_registers[STATUSRSSI] & STC) != 0); } // _waitEnd() _Bool SI4703init(void) { GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = SDA_Pin|SCL_Pin; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; HAL_GPIO_Init(GPIOB, &GPIO_InitStruct); HAL_GPIO_WritePin(SI_RST_GPIO_Port,SI_RST_Pin,GPIO_PIN_SET); HAL_GPIO_WritePin(SDA_GPIO_Port,SDA_Pin,GPIO_PIN_SET); delay_ms(5); /* Min 100us */ HAL_GPIO_WritePin(SDA_GPIO_Port,SDA_Pin,GPIO_PIN_RESET); delay_ms(5); /* Min 100us */ HAL_GPIO_WritePin(SI_RST_GPIO_Port,SI_RST_Pin,GPIO_PIN_RESET); delay_ms(10); /* Min 100us */ HAL_GPIO_WritePin(SI_RST_GPIO_Port,SI_RST_Pin,GPIO_PIN_SET); delay_ms(1); HAL_GPIO_WritePin(SDA_GPIO_Port,SDA_Pin,GPIO_PIN_SET); MX_I2C1_Init(); delay_ms(10); readsi4703_registers(); // Read the current register set // registers[0x07] = 0xBC04; //Enable the oscillator, from AN230 page 9, rev 0.5 (DOES NOT WORK, wtf Silicon Labs datasheet?) si4703_registers[0x07] = 0x8100; // Enable the oscillator, from AN230 page 9, rev 0.61 (works) savesi4703_registers(); // Update delay_ms(500); // Wait for clock to settle - from AN230 page 9 SI4703setBand(); SI4703setFrequency(8750); SI4703setMute(0); SI4703setSoftMute(0); SI4703setVolume(10); return 1; } // init() void SI4703_readRegister0A(void) { unsigned char inBuff[32]={0,}; HAL_I2C_Master_Receive(&hi2c1, SI4703, inBuff, 2, 100); si4703_registers[0x0A] = inBuff[0] << 8; si4703_registers[0x0A] |= inBuff[1]; } // _readRegister0A() void readsi4703_registers(void) { unsigned char inBuff[32]={0,}; HAL_I2C_Master_Receive(&hi2c1, SI4703, inBuff, 32, 100); unsigned char i = 0; for(int x = 0x0A ; ; x++) { //Read in these 32 bytes if(x == 0x10) x = 0; //Loop back to zero si4703_registers[x] = inBuff[i] << 8; i++; si4703_registers[x] |= inBuff[i]; i++; if(x == 0x09) break; //We're done! } } char savesi4703_registers(void) { unsigned char outBuff[32]={0,}; unsigned char i = 0; for(int regSpot = 0x02 ; regSpot < 0x08 ; regSpot++) { unsigned char high_byte = si4703_registers[regSpot] >> 8; unsigned char low_byte = si4703_registers[regSpot] & 0x00FF; outBuff[i]= high_byte; i++; outBuff[i] = low_byte; i++; //Wire.write(high_byte); //Upper 8 bits //Wire.write(low_byte); //Lower 8 bits } HAL_I2C_Master_Transmit(&hi2c1, SI4703, outBuff, 32, 100); //End this transmission //char ack = Wire.endTransmission(); //if(ack != 0) { //We have a problem! // return(0); //} return(1); }