diff --git a/firmware/hw_layer/mc33816.cpp b/firmware/hw_layer/mc33816.cpp index e6d021c1a9..ed9a3b976e 100644 --- a/firmware/hw_layer/mc33816.cpp +++ b/firmware/hw_layer/mc33816.cpp @@ -25,6 +25,8 @@ EXTERN_CONFIG; static OutputPin chipSelect; +static OutputPin resetB; +static OutputPin driven; static SPIConfig spiCfg = { .circular = false, .end_cb = NULL, @@ -34,8 +36,8 @@ static SPIConfig spiCfg = { .circular = false, SPI_CR1_16BIT_MODE | SPI_CR1_MSTR | //SPI_CR1_BR_1 // 5MHz - SPI_CR1_CPHA | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_BR_2, - .cr2 = 0}; + SPI_CR1_CPHA | SPI_CR1_BR_0 | SPI_CR1_BR_1 | SPI_CR1_BR_2 | SPI_CR1_SPE, + .cr2 = SPI_CR2_SSOE}; static SPIDriver *driver; @@ -44,15 +46,219 @@ static void showStats() { } -static void send_16bit_SPI(short param) { - spiSelect(driver); - // we are in 16 bit mode so '1' means 16 bits word hopefully? +// Mostly unused +unsigned short recv_16bit_spi() { + unsigned short ret; + //spiSelect(driver); + spiReceive(driver, 1, &ret); + //spiUnselect(driver); + return ret; +} + +// This could be used to detect if check byte is wrong.. or use a FLAG after init +unsigned short txrx_16bit_spi(const unsigned short param) { + unsigned short ret; + //spiSelect(driver); + spiExchange(driver, 1, ¶m, &ret); + //spiUnselect(driver); + return ret; +} + +// Send 16bits +static void spi_writew(unsigned short param) { + //spiSelect(driver); spiSend(driver, 1, ¶m); + //spiUnselect(driver); +} + +static unsigned short id() { + spiSelect(driver); + spi_writew(0xBAA1); + unsigned short ID = recv_16bit_spi(); + spiUnselect(driver); + return ID; +} + +static void setup_spi() { + spiSelect(driver); + // Select Channel command + spi_writew(0x7FE1); + // Common Page + spi_writew(0x0004); + + + // Configure SPI command + spi_writew(0x3901); + // Mode A + Watchdog timer full + //spi_writew(0x001F); + spi_writew(0x009F); // + fast slew rate on miso spiUnselect(driver); } -static void sentWord(int word) { - send_16bit_SPI(word); +static void enable_flash() +{ + spiSelect(driver); + spi_writew(0x2001); //ch1 + spi_writew(0x0018); //enable flash + spi_writew(0x2401); //ch2 + spi_writew(0x0018); // enable flash + spiUnselect(driver); +} + +static void download_RAM(int target) { + unsigned short memory_area = 0; // memory area + unsigned short start_address = 0; // start address + unsigned short codeWidthRegAddr = 0; // code width register address + unsigned short size = 0; // size of RAM data + unsigned short command = 0; // command data + unsigned short data = 0; // RAM data + unsigned int k = 0; // used in loop for writing RAM data to the chip + const unsigned short *RAM_ptr; // pointer to array of data to be sent to the chip + + + //Why Again? For Every time, just in case? + setup_spi(); + + switch(target) // selects target + { + case CODE_RAM1: + memory_area = 0x1; + start_address = 0; + codeWidthRegAddr = 0x107; + RAM_ptr = MC33816_code_RAM1; + size = sizeof(MC33816_code_RAM1) / 2; + break; + + case CODE_RAM2: + memory_area = 0x2; + start_address = 0; + codeWidthRegAddr = 0x127; + RAM_ptr = MC33816_code_RAM2; + size = sizeof(MC33816_code_RAM2) / 2; + break; + + case DATA_RAM: // ch1 only? + memory_area = 0x4; + start_address = 0; + RAM_ptr = MC33816_data_RAM; + size = sizeof(MC33816_data_RAM) / 2; + break; +// optional, both data_rams with 0x3, writes same code to both + default: + break; + } + + // Chip-Select high + spiSelect(driver); + + if (target != DATA_RAM) + { + command = codeWidthRegAddr << 5; // control width register address + command |= 1; // number of words to follow + spi_writew(command); // sends code_width command + spi_writew(size); // sends size (Code Width) + } + + // Select Channel command + spi_writew(0x7FE1); + // RAM1, RAM2, or Common Page (Data RAM) + spi_writew(memory_area); + + // "Command" of starting address + // up to 0x03FE of code ram + // up to 0x0080 of data ram + command = start_address << 5; + spi_writew(command); // sends start address command + + /* + for(k = 0; k < size; k++) // downloads RAM + { + data = *RAM_ptr; // retrieves data to be sent + spi_writew(data); // sends data + RAM_ptr++; + } + */ + spiSend(driver, size, RAM_ptr); + spiUnselect(driver); +} + +static void download_register(int r_target) { + unsigned short r_start_address = 0; // start address + unsigned short r_size = 0; // size of configuration data + unsigned short r_command = 0; // command data + unsigned short r_data = 0; // configuration data + int n = 0; // used for loop for writing data to the chip + unsigned short remainder_size = 0; // remainder size + const unsigned short *reg_ptr; // pointer to array of data to be sent to the chip + + switch(r_target) // selects target + { + case REG_CH1: // channel 1 configurations + r_start_address = 0x100; + reg_ptr = MC33816_ch1_config; + r_size = sizeof(MC33816_ch1_config) / 2; // gets number of words to be sent + break; + + case REG_CH2: // channel 2 configurations + r_start_address = 0x120; + reg_ptr = MC33816_ch2_config; + r_size = sizeof(MC33816_ch2_config) / 2; // gets number of words to be sent + break; + + case REG_DIAG: // diagnostic configurations + r_start_address = 0x140; + reg_ptr = MC33816_diag_config; + r_size = sizeof(MC33816_diag_config) / 2; // gets number of words to be sent + break; + + case REG_IO: // IO configurations + r_start_address = 0x180; + reg_ptr = MC33816_io_config; + r_size = sizeof(MC33816_io_config) / 2; // gets number of words to be sent + break; + + case REG_MAIN: // main configurations + r_start_address = 0x1C0; + reg_ptr = MC33816_main_config; + r_size = sizeof(MC33816_main_config) / 2; // gets number of words to be sent + break; + + default: + break; + } + + //for location < size(remainder?) + // is location == 0? or past max xfer, send command + expected size + // if location = max xfer + // + // retrieve data, send it, increase pointer + // increase + + if(r_size > MAX_SPI_MODE_A_TRANSFER_SIZE) //if size is too large, split into two sections ... MULTIPLE sections.. + { + remainder_size = r_size - MAX_SPI_MODE_A_TRANSFER_SIZE; // creates remaining size + r_size = MAX_SPI_MODE_A_TRANSFER_SIZE; // sets first size + } + + r_command = r_start_address << 5; // start address + r_command += r_size; // number of words to follow + + spiSelect(driver); // Chip + + spi_writew(r_command); // sends address and number of words to be sent + + spiSend(driver, r_size, reg_ptr); + + if(remainder_size > 0) // if remainder size is greater than 0, download the rest + { + r_start_address += r_size; // new start address + r_command = r_start_address << 5; // start address + r_command += remainder_size; // number of words to follow + + spi_writew(r_command); // sends address and number of words to be sent + spiSend(driver, remainder_size, reg_ptr + r_size); + } + spiUnselect(driver); } void initMc33816() { @@ -61,12 +267,18 @@ void initMc33816() { // default spi3sckPin PB3 // ideally disable isSdCardEnabled since it's on SPI3 - // uncomment thid to hard-code something - //CONFIG(mc33816_cs) = GPIOD_7; + // uncomment this to hard-code something + CONFIG(mc33816_cs) = GPIOD_7; + CONFIG(mc33816_rstb) = GPIOD_5; + CONFIG(mc33816_driven) = GPIOD_6; + // and more to add... if (CONFIG(mc33816_cs) == GPIO_UNASSIGNED) return; + // Initialize the chip via ResetB + resetB.initPin("mc33 RESTB", engineConfiguration->mc33816_rstb); + chipSelect.initPin("mc33 CS", engineConfiguration->mc33816_cs /*, &engineConfiguration->csPinMode*/); spiCfg.ssport = getHwPort("hip", CONFIG(mc33816_cs)); @@ -83,21 +295,49 @@ void initMc33816() { spiStart(driver, &spiCfg); - addConsoleAction("mc33_stats", showStats); + //addConsoleAction("mc33_stats", showStats); + //addConsoleActionI("mc33_send", sendWord); - addConsoleActionI("mc33_send", sentWord); + // Does starting turn this high to begin with?? + spiUnselect(driver); - int size = 105; + //delay/wait? .. possibly only 30us for each needed, per datasheet + resetB.setValue(0); + chThdSleepMilliseconds(10); + resetB.setValue(1); + chThdSleepMilliseconds(10); - unsigned short * RAM_ptr = MC33816_code_RAM1; + setup_spi(); + int mc_id = id(); - for (int k = 0; k < size; k++) // downloads RAM - { - short data = *RAM_ptr; // retrieves data to be sent - send_16bit_SPI(data); // sends data - RAM_ptr++; - } + download_RAM(CODE_RAM1); // transfers code RAM1 + download_RAM(CODE_RAM2); // transfers code RAM2 + download_RAM(DATA_RAM); // transfers data RAM + download_register(REG_MAIN); // download main register configurations + download_register(REG_CH1); // download channel 1 register configurations + download_register(REG_CH2); // download channel 2 register configurations + download_register(REG_IO); // download IO register configurations + download_register(REG_DIAG); // download diag register configuration + enable_flash(); + //driven.setValue(1); // driven = HV +} +void update_scv(unsigned short current) +{ + // Update a single word in Data RAM + spiSelect(driver); + // Select Channel command + spi_writew(0x7FE1); + // Common Page + spi_writew(0x0004); + // write (MSB=0) at data ram x9 (SCV_I_Hold), and 1 word + spi_writew((9 << 5) + 1); + spi_writew(current); + spiUnselect(driver); + + // Strobe it to reload the value + //GPIO_ClearPinsOutput(GPIOE, 1<