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@12:a25bdf135348, 2019-01-14 (annotated)
- Committer:
- JonFreeman
- Date:
- Mon Jan 14 16:39:41 2019 +0000
- Revision:
- 12:a25bdf135348
- Parent:
- 9:644867052318
Tidied, better documented, more OOP, interim release
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
JonFreeman | 4:67478861c670 | 1 | #include "mbed.h" |
JonFreeman | 4:67478861c670 | 2 | #include "Electric_Loco.h" |
JonFreeman | 4:67478861c670 | 3 | |
JonFreeman | 4:67478861c670 | 4 | #include "QSPI_DISCO_F746NG.h" |
JonFreeman | 4:67478861c670 | 5 | |
JonFreeman | 12:a25bdf135348 | 6 | extern error_handling_Jan_2019 Controller_Error ; |
JonFreeman | 12:a25bdf135348 | 7 | |
JonFreeman | 4:67478861c670 | 8 | struct log_element { |
JonFreeman | 9:644867052318 | 9 | uint32_t pulsetot; // Total distance ever in metres |
JonFreeman | 4:67478861c670 | 10 | uint16_t powerW; // during previous second |
JonFreeman | 4:67478861c670 | 11 | uint16_t volts; // during previous second |
JonFreeman | 4:67478861c670 | 12 | } ; |
JonFreeman | 4:67478861c670 | 13 | |
JonFreeman | 4:67478861c670 | 14 | static const int START_BANK = 97; // Which 4k segment to start at |
JonFreeman | 4:67478861c670 | 15 | static const int BANKS_4K = 4; // Numof 4k byte pages used to store recent records |
JonFreeman | 4:67478861c670 | 16 | |
JonFreeman | 4:67478861c670 | 17 | QSPI_DISCO_F746NG qspi; |
JonFreeman | 4:67478861c670 | 18 | extern Serial pc; |
JonFreeman | 5:21a8ac83142c | 19 | //extern uint32_t historic_distance; no longer exkists Apr 2018 |
JonFreeman | 4:67478861c670 | 20 | |
JonFreeman | 4:67478861c670 | 21 | QSPI_Info pQSPI_Info; |
JonFreeman | 4:67478861c670 | 22 | |
JonFreeman | 4:67478861c670 | 23 | bool qspimemcheck () { |
JonFreeman | 4:67478861c670 | 24 | qspi.GetInfo(&pQSPI_Info); |
JonFreeman | 4:67478861c670 | 25 | if ((pQSPI_Info.FlashSize != N25Q128A_FLASH_SIZE) || |
JonFreeman | 4:67478861c670 | 26 | (pQSPI_Info.EraseSectorSize != N25Q128A_SUBSECTOR_SIZE) || |
JonFreeman | 4:67478861c670 | 27 | (pQSPI_Info.ProgPageSize != N25Q128A_PAGE_SIZE) || |
JonFreeman | 4:67478861c670 | 28 | (pQSPI_Info.EraseSectorsNumber != N25Q128A_SUBSECTOR_SIZE) || |
JonFreeman | 4:67478861c670 | 29 | (pQSPI_Info.ProgPagesNumber != N25Q128A_SECTOR_SIZE)) |
JonFreeman | 4:67478861c670 | 30 | { |
JonFreeman | 4:67478861c670 | 31 | error("Get informations FAILED\r\n"); |
JonFreeman | 12:a25bdf135348 | 32 | return false; // Controller_Error.set gets called from main ; |
JonFreeman | 4:67478861c670 | 33 | } |
JonFreeman | 4:67478861c670 | 34 | else |
JonFreeman | 4:67478861c670 | 35 | { |
JonFreeman | 12:a25bdf135348 | 36 | /* pc.printf("Get N25Q128A QSPI mem informations PASSED\r\n"); |
JonFreeman | 4:67478861c670 | 37 | pc.printf ("FLASH_SIZE\t\t%d\r\n", N25Q128A_FLASH_SIZE); |
JonFreeman | 4:67478861c670 | 38 | pc.printf ("ERASE_SECTOR_SIZE\t%d\r\n", N25Q128A_SUBSECTOR_SIZE); |
JonFreeman | 4:67478861c670 | 39 | pc.printf ("PROG_PAGE_SIZE\t\t%d\r\n", N25Q128A_PAGE_SIZE); |
JonFreeman | 4:67478861c670 | 40 | pc.printf ("Erase sectors number\t%d\r\n", N25Q128A_SUBSECTOR_SIZE); |
JonFreeman | 12:a25bdf135348 | 41 | pc.printf ("N25Q128A_SECTOR_SIZE\t%d\r\n", N25Q128A_SECTOR_SIZE); */ |
JonFreeman | 4:67478861c670 | 42 | return true; |
JonFreeman | 4:67478861c670 | 43 | } |
JonFreeman | 4:67478861c670 | 44 | } |
JonFreeman | 4:67478861c670 | 45 | |
JonFreeman | 12:a25bdf135348 | 46 | bool test_qspi () { |
JonFreeman | 12:a25bdf135348 | 47 | if ((qspi.Init() == QSPI_OK) && (qspimemcheck ())) |
JonFreeman | 12:a25bdf135348 | 48 | return true; |
JonFreeman | 12:a25bdf135348 | 49 | return false; |
JonFreeman | 4:67478861c670 | 50 | } |
JonFreeman | 4:67478861c670 | 51 | |
JonFreeman | 4:67478861c670 | 52 | void show_bank (uint32_t bank) { |
JonFreeman | 4:67478861c670 | 53 | uint8_t bu[4096]; |
JonFreeman | 4:67478861c670 | 54 | struct log_element * p = (log_element *)bu; |
JonFreeman | 4:67478861c670 | 55 | if (qspi.Read(bu, bank << 12, 4096) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 56 | pc.printf ("Error reading qspi mem in show_bank\r\n"); |
JonFreeman | 12:a25bdf135348 | 57 | Controller_Error.set (FAULT_QSPI, 1); |
JonFreeman | 4:67478861c670 | 58 | return ; |
JonFreeman | 4:67478861c670 | 59 | } |
JonFreeman | 4:67478861c670 | 60 | pc.printf ("Listing records in bank %d\r\n", bank); |
JonFreeman | 4:67478861c670 | 61 | for (int i = 0; i < 4095 / sizeof(struct log_element); i++) { |
JonFreeman | 4:67478861c670 | 62 | pc.printf ("p->pulsetot%ld, powerW %d, volts %d, addr %lx\r\n", p->pulsetot, p->powerW, p->volts, (uint32_t)p++); |
JonFreeman | 4:67478861c670 | 63 | } |
JonFreeman | 4:67478861c670 | 64 | } |
JonFreeman | 4:67478861c670 | 65 | |
JonFreeman | 4:67478861c670 | 66 | void show_all_banks (); |
JonFreeman | 4:67478861c670 | 67 | void show_all_banks () { |
JonFreeman | 4:67478861c670 | 68 | for (int bank = START_BANK; bank < START_BANK + BANKS_4K; bank++) |
JonFreeman | 4:67478861c670 | 69 | show_bank (bank); |
JonFreeman | 4:67478861c670 | 70 | } |
JonFreeman | 4:67478861c670 | 71 | |
JonFreeman | 4:67478861c670 | 72 | class distance_measurement { |
JonFreeman | 7:3b1f44cd4735 | 73 | uint32_t total_distance; // Replaces historic_distance from previous iterations |
JonFreeman | 4:67478861c670 | 74 | uint32_t bank; |
JonFreeman | 4:67478861c670 | 75 | uint32_t ptr; |
JonFreeman | 4:67478861c670 | 76 | uint8_t buff[4096]; // Reqd qspi ram 4k at a time into here |
JonFreeman | 4:67478861c670 | 77 | |
JonFreeman | 4:67478861c670 | 78 | bool test_element_free (uint8_t* p) ; |
JonFreeman | 4:67478861c670 | 79 | bool test_bank_free (uint32_t addr) ; |
JonFreeman | 4:67478861c670 | 80 | bool test_buff_free () ; |
JonFreeman | 4:67478861c670 | 81 | public: |
JonFreeman | 4:67478861c670 | 82 | bool zero () ; |
JonFreeman | 7:3b1f44cd4735 | 83 | uint32_t out () ; |
JonFreeman | 4:67478861c670 | 84 | bool update (uint32_t pulsetot, uint16_t pow, uint16_t volt) ; |
JonFreeman | 4:67478861c670 | 85 | |
JonFreeman | 4:67478861c670 | 86 | distance_measurement () { // Constructor |
JonFreeman | 4:67478861c670 | 87 | uint32_t obank = 0, optr = 0, lptr = 0; |
JonFreeman | 4:67478861c670 | 88 | bool free_elem_found = false; |
JonFreeman | 4:67478861c670 | 89 | qspi.Init (); |
JonFreeman | 4:67478861c670 | 90 | |
JonFreeman | 4:67478861c670 | 91 | bank = START_BANK; |
JonFreeman | 4:67478861c670 | 92 | while (bank < START_BANK + BANKS_4K && !free_elem_found) { |
JonFreeman | 4:67478861c670 | 93 | if (qspi.Read(buff, bank << 12, 4096) != QSPI_OK) { |
JonFreeman | 12:a25bdf135348 | 94 | Controller_Error.set (FAULT_QSPI, 1); |
JonFreeman | 12:a25bdf135348 | 95 | // pc.printf ("Error reading qspi mem\r\n"); |
JonFreeman | 4:67478861c670 | 96 | } |
JonFreeman | 4:67478861c670 | 97 | for (ptr = 0; !free_elem_found && ptr < 4096; ptr += sizeof(struct log_element)) { |
JonFreeman | 4:67478861c670 | 98 | free_elem_found = test_element_free (&buff[ptr]); |
JonFreeman | 4:67478861c670 | 99 | if (free_elem_found) { |
JonFreeman | 4:67478861c670 | 100 | obank = bank; |
JonFreeman | 4:67478861c670 | 101 | optr = ptr; |
JonFreeman | 12:a25bdf135348 | 102 | // pc.printf ("Found free element at bank %d, ptr %x\r\n", bank, ptr); |
JonFreeman | 4:67478861c670 | 103 | } |
JonFreeman | 4:67478861c670 | 104 | else { // Not free element found |
JonFreeman | 4:67478861c670 | 105 | lptr = ptr; |
JonFreeman | 4:67478861c670 | 106 | } |
JonFreeman | 4:67478861c670 | 107 | } |
JonFreeman | 4:67478861c670 | 108 | bank++; |
JonFreeman | 4:67478861c670 | 109 | } |
JonFreeman | 4:67478861c670 | 110 | bank = obank; |
JonFreeman | 4:67478861c670 | 111 | ptr = optr; |
JonFreeman | 4:67478861c670 | 112 | struct log_element * p = (log_element *)(buff + lptr); |
JonFreeman | 5:21a8ac83142c | 113 | |
JonFreeman | 7:3b1f44cd4735 | 114 | // historic_distance = p->pulsetot; // This needs replacing |
JonFreeman | 7:3b1f44cd4735 | 115 | total_distance = p->pulsetot; // New May 2018, total_distance is metres. Update info arrives in mm. |
JonFreeman | 5:21a8ac83142c | 116 | |
JonFreeman | 12:a25bdf135348 | 117 | // 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); |
JonFreeman | 4:67478861c670 | 118 | } // endof constructor |
JonFreeman | 4:67478861c670 | 119 | } odometer; |
JonFreeman | 4:67478861c670 | 120 | |
JonFreeman | 4:67478861c670 | 121 | |
JonFreeman | 4:67478861c670 | 122 | bool distance_measurement::test_element_free (uint8_t* p) { |
JonFreeman | 4:67478861c670 | 123 | for (int i = 0; i < sizeof(log_element); i++) |
JonFreeman | 4:67478861c670 | 124 | if (*(p + i) != 0xff) |
JonFreeman | 4:67478861c670 | 125 | return false; |
JonFreeman | 4:67478861c670 | 126 | return true; |
JonFreeman | 4:67478861c670 | 127 | } |
JonFreeman | 4:67478861c670 | 128 | |
JonFreeman | 4:67478861c670 | 129 | bool distance_measurement::test_buff_free () { |
JonFreeman | 4:67478861c670 | 130 | for (int i = 0; i < 4096; i++) |
JonFreeman | 4:67478861c670 | 131 | if (buff[i] != 0xff) |
JonFreeman | 4:67478861c670 | 132 | return false; |
JonFreeman | 4:67478861c670 | 133 | return true; |
JonFreeman | 4:67478861c670 | 134 | } |
JonFreeman | 4:67478861c670 | 135 | |
JonFreeman | 4:67478861c670 | 136 | bool distance_measurement::test_bank_free (uint32_t addr) { |
JonFreeman | 4:67478861c670 | 137 | if (qspi.Read (buff, addr & 0xfffff000, 4096) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 138 | pc.printf ("Read error in test_bank_free\r\n"); |
JonFreeman | 4:67478861c670 | 139 | return false; |
JonFreeman | 4:67478861c670 | 140 | } |
JonFreeman | 4:67478861c670 | 141 | return test_buff_free (); |
JonFreeman | 4:67478861c670 | 142 | } |
JonFreeman | 4:67478861c670 | 143 | |
JonFreeman | 4:67478861c670 | 144 | bool distance_measurement::zero () { |
JonFreeman | 4:67478861c670 | 145 | bool rv = true; |
JonFreeman | 7:3b1f44cd4735 | 146 | total_distance = 0; |
JonFreeman | 4:67478861c670 | 147 | for (int i = START_BANK; i < START_BANK + BANKS_4K; i++) { |
JonFreeman | 4:67478861c670 | 148 | if (qspi.Erase_Block(i << 12) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 149 | pc.printf ("Error zeroing odometer!\r\n"); |
JonFreeman | 4:67478861c670 | 150 | rv = false; |
JonFreeman | 4:67478861c670 | 151 | } |
JonFreeman | 4:67478861c670 | 152 | if (!test_bank_free (i << 12)) |
JonFreeman | 4:67478861c670 | 153 | pc.printf ("Bank [%d] not freed in zero\r\n", i); |
JonFreeman | 4:67478861c670 | 154 | else |
JonFreeman | 4:67478861c670 | 155 | pc.printf ("Cleared bank [%d] in zero\r\n", i); |
JonFreeman | 4:67478861c670 | 156 | } |
JonFreeman | 4:67478861c670 | 157 | bank = START_BANK; |
JonFreeman | 4:67478861c670 | 158 | ptr = 0; |
JonFreeman | 4:67478861c670 | 159 | return rv; |
JonFreeman | 4:67478861c670 | 160 | } |
JonFreeman | 4:67478861c670 | 161 | |
JonFreeman | 7:3b1f44cd4735 | 162 | bool distance_measurement::update (uint32_t new_metres_travelled, uint16_t powr, uint16_t volt) { |
JonFreeman | 4:67478861c670 | 163 | bool rv = true; |
JonFreeman | 7:3b1f44cd4735 | 164 | total_distance += new_metres_travelled; |
JonFreeman | 4:67478861c670 | 165 | struct log_element d; |
JonFreeman | 7:3b1f44cd4735 | 166 | d.pulsetot = total_distance; |
JonFreeman | 4:67478861c670 | 167 | d.powerW = powr; |
JonFreeman | 4:67478861c670 | 168 | d.volts = volt; |
JonFreeman | 4:67478861c670 | 169 | uint32_t addr = ptr + (bank << 12); |
JonFreeman | 4:67478861c670 | 170 | if (qspi.Write ((uint8_t*)&d, addr, sizeof(struct log_element)) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 171 | pc.printf ("Write error in odometer update\r\n"); |
JonFreeman | 4:67478861c670 | 172 | qspi.Init(); // Attempt error recovery |
JonFreeman | 4:67478861c670 | 173 | return false; |
JonFreeman | 4:67478861c670 | 174 | } |
JonFreeman | 4:67478861c670 | 175 | ptr += sizeof(struct log_element); |
JonFreeman | 4:67478861c670 | 176 | if (ptr >= 4096) { |
JonFreeman | 4:67478861c670 | 177 | ptr -= 4096; |
JonFreeman | 4:67478861c670 | 178 | bank++; |
JonFreeman | 4:67478861c670 | 179 | if (bank >= START_BANK + BANKS_4K) |
JonFreeman | 4:67478861c670 | 180 | bank = START_BANK; |
JonFreeman | 4:67478861c670 | 181 | //erase bank |
JonFreeman | 4:67478861c670 | 182 | pc.printf ("About to erase bank %d\r\n", bank); |
JonFreeman | 4:67478861c670 | 183 | if (qspi.Erase_Block(bank << 12) != QSPI_OK) { |
JonFreeman | 4:67478861c670 | 184 | pc.printf ("Erase error in odometer update\r\n"); |
JonFreeman | 4:67478861c670 | 185 | rv = false; |
JonFreeman | 4:67478861c670 | 186 | } |
JonFreeman | 4:67478861c670 | 187 | } |
JonFreeman | 4:67478861c670 | 188 | return rv; |
JonFreeman | 4:67478861c670 | 189 | } |
JonFreeman | 4:67478861c670 | 190 | |
JonFreeman | 7:3b1f44cd4735 | 191 | uint32_t distance_measurement::out () { |
JonFreeman | 7:3b1f44cd4735 | 192 | return total_distance; |
JonFreeman | 7:3b1f44cd4735 | 193 | } |
JonFreeman | 7:3b1f44cd4735 | 194 | |
JonFreeman | 7:3b1f44cd4735 | 195 | |
JonFreeman | 4:67478861c670 | 196 | bool odometer_zero () ; // Returns true on success |
JonFreeman | 4:67478861c670 | 197 | bool odometer_zero () { // Returns true on success |
JonFreeman | 4:67478861c670 | 198 | return odometer.zero (); |
JonFreeman | 4:67478861c670 | 199 | } |
JonFreeman | 4:67478861c670 | 200 | |
JonFreeman | 4:67478861c670 | 201 | 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 |
JonFreeman | 4:67478861c670 | 202 | 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 |
JonFreeman | 4:67478861c670 | 203 | return odometer.update (pulsetot, pow, volt); |
JonFreeman | 4:67478861c670 | 204 | } |
JonFreeman | 4:67478861c670 | 205 | |
JonFreeman | 7:3b1f44cd4735 | 206 | uint32_t odometer_out () { |
JonFreeman | 7:3b1f44cd4735 | 207 | return odometer.out(); |
JonFreeman | 7:3b1f44cd4735 | 208 | } |