Touch screen drivers control dashboard for miniature locomotive. Features meters for speed, volts, power. Switches for lights, horns. Drives multiple STM3_ESC brushless motor controllers for complete brushless loco system as used in "The Brute" - www.jons-workshop.com
Dependencies: TS_DISCO_F746NG mbed Servo LCD_DISCO_F746NG BSP_DISCO_F746NG QSPI_DISCO_F746NG AsyncSerial FastPWM
qspi_mem.cpp
00001 #include "mbed.h" 00002 #include "Electric_Loco.h" 00003 00004 #include "QSPI_DISCO_F746NG.h" 00005 00006 extern error_handling_Jan_2019 Controller_Error ; 00007 00008 struct log_element { 00009 uint32_t pulsetot; // Total distance ever in metres 00010 uint16_t powerW; // during previous second 00011 uint16_t volts; // during previous second 00012 } ; 00013 00014 static const int START_BANK = 97; // Which 4k segment to start at 00015 static const int BANKS_4K = 4; // Numof 4k byte pages used to store recent records 00016 00017 QSPI_DISCO_F746NG qspi; 00018 extern Serial pc; 00019 //extern uint32_t historic_distance; no longer exkists Apr 2018 00020 00021 QSPI_Info pQSPI_Info; 00022 00023 bool qspimemcheck () { 00024 qspi.GetInfo(&pQSPI_Info); 00025 if ((pQSPI_Info.FlashSize != N25Q128A_FLASH_SIZE) || 00026 (pQSPI_Info.EraseSectorSize != N25Q128A_SUBSECTOR_SIZE) || 00027 (pQSPI_Info.ProgPageSize != N25Q128A_PAGE_SIZE) || 00028 (pQSPI_Info.EraseSectorsNumber != N25Q128A_SUBSECTOR_SIZE) || 00029 (pQSPI_Info.ProgPagesNumber != N25Q128A_SECTOR_SIZE)) 00030 { 00031 error("Get informations FAILED\r\n"); 00032 return false; // Controller_Error.set gets called from main ; 00033 } 00034 else 00035 { 00036 /* pc.printf("Get N25Q128A QSPI mem informations PASSED\r\n"); 00037 pc.printf ("FLASH_SIZE\t\t%d\r\n", N25Q128A_FLASH_SIZE); 00038 pc.printf ("ERASE_SECTOR_SIZE\t%d\r\n", N25Q128A_SUBSECTOR_SIZE); 00039 pc.printf ("PROG_PAGE_SIZE\t\t%d\r\n", N25Q128A_PAGE_SIZE); 00040 pc.printf ("Erase sectors number\t%d\r\n", N25Q128A_SUBSECTOR_SIZE); 00041 pc.printf ("N25Q128A_SECTOR_SIZE\t%d\r\n", N25Q128A_SECTOR_SIZE); */ 00042 return true; 00043 } 00044 } 00045 00046 bool test_qspi () { 00047 if ((qspi.Init() == QSPI_OK) && (qspimemcheck ())) 00048 return true; 00049 return false; 00050 } 00051 00052 void show_bank (uint32_t bank) { 00053 uint8_t bu[4096]; 00054 struct log_element * p = (log_element *)bu; 00055 if (qspi.Read(bu, bank << 12, 4096) != QSPI_OK) { 00056 pc.printf ("Error reading qspi mem in show_bank\r\n"); 00057 Controller_Error.set (FAULT_QSPI, 1); 00058 return ; 00059 } 00060 pc.printf ("Listing records in bank %d\r\n", bank); 00061 for (int i = 0; i < 4095 / sizeof(struct log_element); i++) { 00062 pc.printf ("p->pulsetot%ld, powerW %d, volts %d, addr %lx\r\n", p->pulsetot, p->powerW, p->volts, (uint32_t)p++); 00063 } 00064 } 00065 00066 void show_all_banks (); 00067 void show_all_banks () { 00068 for (int bank = START_BANK; bank < START_BANK + BANKS_4K; bank++) 00069 show_bank (bank); 00070 } 00071 00072 class distance_measurement { 00073 uint32_t total_distance; // Replaces historic_distance from previous iterations 00074 uint32_t bank; 00075 uint32_t ptr; 00076 uint8_t buff[4096]; // Reqd qspi ram 4k at a time into here 00077 00078 bool test_element_free (uint8_t* p) ; 00079 bool test_bank_free (uint32_t addr) ; 00080 bool test_buff_free () ; 00081 public: 00082 bool zero () ; 00083 uint32_t out () ; 00084 bool update (uint32_t pulsetot, uint16_t pow, uint16_t volt) ; 00085 00086 distance_measurement () { // Constructor 00087 uint32_t obank = 0, optr = 0, lptr = 0; 00088 bool free_elem_found = false; 00089 qspi.Init (); 00090 00091 bank = START_BANK; 00092 while (bank < START_BANK + BANKS_4K && !free_elem_found) { 00093 if (qspi.Read(buff, bank << 12, 4096) != QSPI_OK) { 00094 Controller_Error.set (FAULT_QSPI, 1); 00095 // pc.printf ("Error reading qspi mem\r\n"); 00096 } 00097 for (ptr = 0; !free_elem_found && ptr < 4096; ptr += sizeof(struct log_element)) { 00098 free_elem_found = test_element_free (&buff[ptr]); 00099 if (free_elem_found) { 00100 obank = bank; 00101 optr = ptr; 00102 // pc.printf ("Found free element at bank %d, ptr %x\r\n", bank, ptr); 00103 } 00104 else { // Not free element found 00105 lptr = ptr; 00106 } 00107 } 00108 bank++; 00109 } 00110 bank = obank; 00111 ptr = optr; 00112 struct log_element * p = (log_element *)(buff + lptr); 00113 00114 // historic_distance = p->pulsetot; // This needs replacing 00115 total_distance = p->pulsetot; // New May 2018, total_distance is metres. Update info arrives in mm. 00116 00117 // pc.printf ("Constructor found free elem at bank %d, position %d, previous total %ld, volts %.3f\r\n", bank, ptr, p->pulsetot, ((double)p->volts) / 500.0); 00118 } // endof constructor 00119 } odometer; 00120 00121 00122 bool distance_measurement::test_element_free (uint8_t* p) { 00123 for (int i = 0; i < sizeof(log_element); i++) 00124 if (*(p + i) != 0xff) 00125 return false; 00126 return true; 00127 } 00128 00129 bool distance_measurement::test_buff_free () { 00130 for (int i = 0; i < 4096; i++) 00131 if (buff[i] != 0xff) 00132 return false; 00133 return true; 00134 } 00135 00136 bool distance_measurement::test_bank_free (uint32_t addr) { 00137 if (qspi.Read (buff, addr & 0xfffff000, 4096) != QSPI_OK) { 00138 pc.printf ("Read error in test_bank_free\r\n"); 00139 return false; 00140 } 00141 return test_buff_free (); 00142 } 00143 00144 bool distance_measurement::zero () { 00145 bool rv = true; 00146 total_distance = 0; 00147 for (int i = START_BANK; i < START_BANK + BANKS_4K; i++) { 00148 if (qspi.Erase_Block(i << 12) != QSPI_OK) { 00149 pc.printf ("Error zeroing odometer!\r\n"); 00150 rv = false; 00151 } 00152 if (!test_bank_free (i << 12)) 00153 pc.printf ("Bank [%d] not freed in zero\r\n", i); 00154 else 00155 pc.printf ("Cleared bank [%d] in zero\r\n", i); 00156 } 00157 bank = START_BANK; 00158 ptr = 0; 00159 return rv; 00160 } 00161 00162 bool distance_measurement::update (uint32_t new_metres_travelled, uint16_t powr, uint16_t volt) { 00163 bool rv = true; 00164 total_distance += new_metres_travelled; 00165 struct log_element d; 00166 d.pulsetot = total_distance; 00167 d.powerW = powr; 00168 d.volts = volt; 00169 uint32_t addr = ptr + (bank << 12); 00170 if (qspi.Write ((uint8_t*)&d, addr, sizeof(struct log_element)) != QSPI_OK) { 00171 pc.printf ("Write error in odometer update\r\n"); 00172 qspi.Init(); // Attempt error recovery 00173 return false; 00174 } 00175 ptr += sizeof(struct log_element); 00176 if (ptr >= 4096) { 00177 ptr -= 4096; 00178 bank++; 00179 if (bank >= START_BANK + BANKS_4K) 00180 bank = START_BANK; 00181 //erase bank 00182 pc.printf ("About to erase bank %d\r\n", bank); 00183 if (qspi.Erase_Block(bank << 12) != QSPI_OK) { 00184 pc.printf ("Erase error in odometer update\r\n"); 00185 rv = false; 00186 } 00187 } 00188 return rv; 00189 } 00190 00191 uint32_t distance_measurement::out () { 00192 return total_distance; 00193 } 00194 00195 00196 bool odometer_zero () ; // Returns true on success 00197 bool odometer_zero () { // Returns true on success 00198 return odometer.zero (); 00199 } 00200 00201 bool odometer_update (uint32_t pulsetot, uint16_t pow, uint16_t volt) ; // Hall pulse total updated once per sec and saved in blocks of 4096 bytes on QSPI onboard memory 00202 bool odometer_update (uint32_t pulsetot, uint16_t pow, uint16_t volt) { // Hall pulse total updated once per sec and saved in blocks of 4096 bytes on QSPI onboard memory 00203 return odometer.update (pulsetot, pow, volt); 00204 } 00205 00206 uint32_t odometer_out () { 00207 return odometer.out(); 00208 }
Generated on Thu Jul 14 2022 06:50:34 by 1.7.2