diff --git a/FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex b/FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex index c31b82c5..d00b5d68 100644 --- a/FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex +++ b/FluxEngine.cydsn/CortexM3/ARM_GCC_541/Release/FluxEngine.hex @@ -13,35 +13,35 @@ :4003000002F07AFD02A801F08AFF01F094FF13B05DF804EB04B0704710B5044601780648FFF7E5FF0420FFF7EFFE62782146BDE81040042001F080B83A36000007B50023B1 :40034000ADF804308DF80600032301A88DF80530FFF7E2FF03B05DF804FB0000F8B51D4C0646FFF733FF637F03B156B91A48FFF7BEFFFFF75EFF012000236077636302F048 :4003800099F83246616B1548FFF7B1FF114D0027636B9E4216D001F0D7FE00B16F63636B9E4205DD0020FFF72BFF6B6B013305E005DA0120FFF724FF6B6B013B6B6302F059 -:4003C000A1F8E5E7322002F05FF8BDE8F8400448FFF78DBF8081FF1F473600004E3600006B3600002DE9F04F9BB062B602F0F4F8B449042002F018F9B34801F0B1FEB34881 -:4004000002F0E4FBB24801F0E5FE02F0C5FA02F097F9002002F0B8FB01F000FF0221002000F0A4FFAB4D0321084602F04BF82E462C46DFF8C4B202F065F8AB7F73B12A6A5C -:40044000EB689B1A41F28832934207D9002001F075FE002002F098FB0023AB7700F0BEFF18B99D48FFF743FF04E000F0BDFF0028F7D109E000F0B2FF0028FBD09748FFF7F7 -:4004800036FF032001F016F8032000F0B9FF0128D1D19348FFF764FE92490320FFF782FE94F838109048FFF722FF94F83830023B122B00F2F583DFE813F01300F3031C001E -:4004C000F3032200F3034400F3036800F303A001F3033503F3035403F3035A03F303650303238DF828308DF829300A238DF82A3044E394F83A00FFF731FF7C4B3BE3FFF7AE +:4003C000A1F8E5E7322002F05FF8BDE8F8400448FFF78DBF8081FF1F473600004E3600006B3600002DE9F04F9BB062B602F0F4F8B749042002F018F9B64801F0B1FEB64878 +:4004000002F0E4FBB54801F0E5FE02F0C5FA02F097F9002002F0B8FB01F000FF0221002000F0A4FFAE4D0321084602F04BF82E462C46DFF8D4B202F065F8AB7F73B12A6A46 +:40044000EB689B1A41F28832934207D9002001F075FE002002F098FB0023AB7700F0BEFF18B9A048FFF743FF04E000F0BDFF0028F7D109E000F0B2FF0028FBD09A48FFF7F1 +:4004800036FF032001F016F8032000F0B9FF0128D1D19648FFF764FE95490320FFF782FE94F838109348FFF722FF94F83830023B122B00F2F583DFE813F01300F3031C0015 +:4004C000F3032200F3034400F3036800F303A001F3033503F3035403F3035A03F303650303238DF828308DF829300B238DF82A3044E394F83A00FFF731FF7F4B3BE3FFF7AA :4005000065FE00236372E068627A02F0FF0132B9EB681B1AB3F57A7FF6DD0B4608E03BB100227272F168627A12B9EB685B1AFAE707228DF8282004228DF82920ADF82A30A6 :400540001CE30220FFF7E0FD4FF000090DF1280A4FF480780027C8EB0903DA1907F80A200137402FF9D10220FFF7CEFD3A465146022000F061FFB8F10108EBD109F1010983 -:40058000B9F1400FE4D15A4BC7E294F83A0001F0F9FD606BFFF7E2FE02F09AFB554BDFF85C811A78002742F004021A701A7842F001021A701A7802F0FE021A701A7802F0B8 -:4005C000FE021A7002F088FB0220FFF79DFD41F6FF734FF480420121022002F0DBFA84F8780001F0FDFE08F807000137102FF8D1DFF80CA100270AF15D081FFA88F901378D -:40060000102F14BF3A4600221AF8010F2244062392F82420402101F017FF4A4646F242419AF8000001F022FF09F14009102F1FFA89F9E4D100237372637A002BFCD000275B -:40064000142239460AA8777202F0A2FB40230D934FF0FF333760736037723368DFF8A490334493F8241096F87800CDF8309001F06FFE96F8780001F02DFE012196F8780005 -:4006800001F000FECDF81090236813B96B7A002BFAD0002794F83BA0676094F80890B9F1000F08D101F02EFF6B7A83B3BAF1010A85F809902BD1042194F8780001F054FE3D -:4006C0005CE000BF19010000F900000091000000C50000008081FF1F793600008C3600009881FF1FB881FF1F963600002C3600002E360000926400409C640040A481FF1F2D -:40070000A381FF1F0086FF1F2B7A002BD3D1626823689A42F8D04FF0000962680AA808EB82124A440A92C9F140020B9200F0DAFA0B9A0137C2F1400209EB02030D9A5FFAC9 -:4007400083F95AB90220FFF7DFFC4022BC49022000F072FE049B0C9340230D93B9F13F0FDBD96268B74B01321340002BBEBF03F1FF3363F00F03013363608EE794F878002C -:4007800001F002FE0028F9D10AA800F0DFFA0220FFF7BAFC337A63B90D9A402A06D0C2F1400292B2A649022000F046FE0220FFF7ABFC0D9A32F0400206D10220114600F0D5 -:4007C0003BFE0220FFF7A0FCFFF744FD237A33B19D48FFF78CFD0220FFF7B0FD06E09B4B09A81B88ADF82430FFF796FD627A3946237A9748FFF77BFD55E29648FFF777FDC5 +:40058000B9F1400FE4D15D4BC7E294F83A0001F0F9FD606BFFF7E2FE02F09AFB584BDFF86C811A78002742F004021A701A7842F001021A701A7802F0FE021A701A7802F0A2 +:4005C000FE021A7002F088FB0220FFF79DFD41F6FF734FF480420121022002F0DBFA84F8780001F0FDFE08F807000137102FF8D1DFF81CA100270AF15D081FFA88F901377D +:40060000102F14BF3A4600221AF8010F2244062392F82420402101F017FF4A4646F242419AF8000001F022FF09F14009102F1FFA89F9E4D196F83B3033B100237372637A9C +:40064000002BFCD000237372142200210AA802F09FFB40234FF0FF320D9300232360626023722368274F234493F8241094F878000C9701F06DFE94F8780001F02BFE01210C +:4006800094F8780001F0FEFD04972368002BFCD000277760D6F80CA0237A7BB901F032FFA98F04E0EB68CAEB03038B4206D2626823689A422ED12B7A002BF3D094F808801C +:4006C000042194F878005FFA88F801F04DFE54E019010000F900000091000000C50000008081FF1F793600008C3600009881FF1FB881FF1F963600002C3600002E3600006F +:40070000926400400086FF1F9C640040A481FF1FA381FF1F4FF0000962680AA808EB82124A440A92C9F140020B9200F0DBFA0B9A0137C2F1400209EB02030D9A5FFA83F900 +:400740005AB90220FFF7E0FC4022BD49022000F073FE049B0C9340230D93B9F13F0FDBD96268B84B01321340002BBEBF03F1FF3363F00F03013363608EE794F8780001F0B3 +:4007800003FE0028F9D10AA800F0E0FA0220FFF7BBFC0D9B402B07D002204022A84900F04BFE0220FFF7B0FC0D9B022033F040021DBFC3F1400292B2A149114600F03CFEEF +:4007C0000220FFF7A1FCFFF745FDB8F1000F06D09D48FFF78CFD0220FFF7B0FD06E09B4B09A81B88ADF82430FFF796FD627A3946237A9748FFF77BFD55E29648FFF777FDEF :40080000E76B17F03F0701D003204AE2012001F0BFFC95F83A0001F0B5FC02F059FA9BF80030DFF8348203F0FB038BF800309BF8003043F001038BF800309BF8003003F027 :40084000FE038BF800309BF8003003F0FE038BF8003002F041FA686BFFF780FD01214FF4804341F6FF72084601F098FC85F8780001F0B6FD08F807000137102FF8D1DFF88D :40088000DC91002709F15D031FFA83F807930137102F14BF3A46002219F8010F2244052392F82420402101F0CFFD414646F24C4299F8000001F0DAFD08F14008102F1FFA56 -:4008C00088F8E4D10027B946BA46F36B4FF0FF389B09142239460AA837600593C6F80480377202F055FA402301200D9300F0E2FDCDF81880049701F005FE2268514B01322B +:4008C00088F8E4D10027B946BA46F36B4FF0FF389B09142239460AA837600493C6F80480377202F055FA402301200D9300F0E2FDCDF81880059701F005FE2268514B01322B :400900001340002BBCBF03F1FF3363F00F036168B8BF01338B4200F0A380BAF1000F07D0237A002B40F0B0806B7A002B40F0AC800B9B002B34D1B9F1000F0BD07F22404926 :400940005A540133402BFAD10A910B9328E0BAF1000F06D1012000F053FD01288046F6D107E0237A002B40F08F806B7A002BF1D08AE03349FFF716FC8146314B0B90404665 -:400980000A9300F097FDB9F13F0F07F1010706DD059BDB1BD3F1000949EB030900E0C1460B9BDBB12368079A0AA802EB83120D9BC3F1400313440C9300F0D7F90D9B6BB9FE +:400980000A9300F097FDB9F13F0F07F1010706DD049BDB1BD3F1000949EB030900E0C1460B9BDBB12368079A0AA802EB83120D9BC3F1400313440C9300F0D7F90D9B6BB9FF :4009C0002A68204B01321340002BBEBF03F1FF3363F00F030133236040230D93636801333ED12B680F2B3BD14FF00008C5F8048001F002FC85F808806B6895F878002B44DD :400A000093F8241001F0A4FC95F8780001F062FC012195F8780001F035FC85F80980637A002BFCD04FF00008012086F8098001F0EFFB404601F0ACFBCDF8188013E000BF78 -:400A40000086FF1F0F000080A536000030360000BF360000D2360000A481FF1FA381FF1FBAF1000F05D0237A73B96B7A63B94FF0010A6368069A93423FF43DAF049B0133AB -:400A800004936B68069336E701F0BCFB012001F07FFB002001F0BCFB042194F8780001F063FC94F8780001F06FFC0028F9D196F8780001F0FDFB737A327A02930123039279 -:400AC0000193CDF80090049B3A4605997A48FFF70EFCB9F1000F16D1059BBB420ADD012000F08EFC01288046F6D17449FFF75AFB3F2803DC012000F017FD04E0404600F04C +:400A40000086FF1F0F000080A536000030360000BF360000D2360000A481FF1FA381FF1FBAF1000F05D0237A73B96B7A63B94FF0010A6368069A93423FF43DAF059B0133AA +:400A800005936B68069336E701F0BCFB012001F07FFB002001F0BCFB042194F8780001F063FC94F8780001F06FFC0028F9D196F8780001F0FDFB737A327A02930123039278 +:400AC0000193CDF80090059B3A4604997A48FFF70EFCB9F1000F16D1049BBB420ADD012000F08EFC01288046F6D17449FFF75AFB3F2803DC012000F017FD04E0404600F04D :400B0000D9FC0137E8E7FFF7A5FB6D48FFF7EFFB237A0BB10220C4E06A4B1B8809A8ADF824302CE094F83A0001F02CFB606BFFF715FC6548FFF7DBFB00236372637A002B58 :400B4000FCD0012001F064FB00237372637A002BFCD0002001F05CFB5C48FFF7C8FB5C4B09E000206077FFF7F9FB5A4B03E05A48FFF7F6FA594B1B88ADF828300AA8FFF72A :400B8000CBFB90E0A37F3BB1002001F0D7FA002001F0FAFF0023AB7701F07CFF002001F01FFF2A2701F04AFE002001F0EDFD3A4600210AA802F0ECF815238DF828308DF8DD @@ -4615,12 +4615,12 @@ :0200000490105A :04000000BC90ACAF55 :0200000490303A -:0200000004BC3E +:0200000001A954 :0200000490402A :4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C0 :400040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080 :400080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040 :4000C0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 :0200000490501A -:0C00000000012E16106900002E3015259E +:0C00000000012E16106900002E301212B4 :00000001FF \ No newline at end of file diff --git a/FluxEngine.cydsn/main.c b/FluxEngine.cydsn/main.c index d6db3ff9..26d3f9d2 100644 --- a/FluxEngine.cydsn/main.c +++ b/FluxEngine.cydsn/main.c @@ -343,12 +343,15 @@ static void cmd_read(struct read_frame* f) wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); init_capture_dma(); - /* Wait for the beginning of a rotation. */ + /* Wait for the beginning of a rotation, if requested. */ - index_irq = false; - while (!index_irq) - ; - index_irq = false; + if (f->synced) + { + index_irq = false; + while (!index_irq) + ; + index_irq = false; + } crunch_state_t cs = {}; cs.outputptr = usb_buffer; @@ -365,32 +368,27 @@ static void cmd_read(struct read_frame* f) /* Wait for the first DMA transfer to complete, after which we can start the * USB transfer. */ - while ((dma_writing_to_td == 0) && !index_irq) + while (dma_writing_to_td == 0) ; dma_reading_from_td = 0; /* Start transferring. */ - int revolutions = f->revolutions; + uint32_t start_time = clock; while (!dma_underrun) { CyWdtClear(); - /* Have we reached the index pulse? */ - if (index_irq) - { - index_irq = false; - revolutions--; - if (revolutions == 0) - break; - } - /* Wait for the next block to be read. */ while (dma_reading_from_td == dma_writing_to_td) { /* On an underrun, give up immediately. */ if (dma_underrun) goto abort; + + /* Also finish if the sample session is over. */ + if ((clock - start_time) >= f->milliseconds) + goto abort; } uint8_t dma_buffer_usage = 0; @@ -416,26 +414,33 @@ static void cmd_read(struct read_frame* f) dma_reading_from_td = NEXT_BUFFER(dma_reading_from_td); } abort:; + bool saved_dma_underrun = dma_underrun; CyDmaChSetRequest(dma_channel, CY_DMA_CPU_TERM_CHAIN); while (CyDmaChGetRequest(dma_channel)) ; donecrunch(&cs); wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); - if (!dma_underrun) + /* If there's a complete packet waiting, send it. */ + if (cs.outputlen != BUFFER_SIZE) { - if (cs.outputlen != BUFFER_SIZE) - USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen); + USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE); wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); } - if ((cs.outputlen == BUFFER_SIZE) || (cs.outputlen == 0)) + if ((cs.outputlen != 0) && (cs.outputlen != BUFFER_SIZE)) + { + /* If there's a partial packet waiting, send it; this will also terminate the transfer. */ + USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, usb_buffer, BUFFER_SIZE-cs.outputlen); + } + else { + /* Otherwise just terminate the transfer. */ USBFS_LoadInEP(FLUXENGINE_DATA_IN_EP_NUM, NULL, 0); - wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); } + wait_until_writeable(FLUXENGINE_DATA_IN_EP_NUM); deinit_dma(); - if (dma_underrun) + if (saved_dma_underrun) { print("underrun after %d packets"); send_error(F_ERROR_UNDERRUN); diff --git a/lib/fluxsource/fluxsource.h b/lib/fluxsource/fluxsource.h index ac3c3865..e824f6e0 100644 --- a/lib/fluxsource/fluxsource.h +++ b/lib/fluxsource/fluxsource.h @@ -27,8 +27,9 @@ class FluxSource virtual bool retryable() { return false; } }; -extern void setHardwareFluxSourceRevolutions(int revolutions); +extern void setHardwareFluxSourceRevolutions(double revolutions); extern void setHardwareFluxSourceDensity(bool high_density); +extern void setHardwareFluxSourceSynced(bool synced); #endif diff --git a/lib/fluxsource/hardwarefluxsource.cc b/lib/fluxsource/hardwarefluxsource.cc index 5420e184..57cdcd3e 100644 --- a/lib/fluxsource/hardwarefluxsource.cc +++ b/lib/fluxsource/hardwarefluxsource.cc @@ -3,13 +3,19 @@ #include "fluxmap.h" #include "usb.h" #include "fluxsource/fluxsource.h" +#include "fmt/format.h" FlagGroup hardwareFluxSourceFlags; -static IntFlag revolutions( +static DoubleFlag revolutions( { "--revolutions" }, "read this many revolutions of the disk", - 1); + 1.25); + +static BoolFlag synced( + { "--sync-with-index" }, + "whether to wait for an index pulse before started to read", + false); static IntFlag indexMode( { "--index-mode" }, @@ -29,6 +35,10 @@ class HardwareFluxSource : public FluxSource HardwareFluxSource(unsigned drive): _drive(drive) { + usbSetDrive(_drive, high_density, indexMode); + std::cerr << "Measuring rotational speed... " << std::flush; + _oneRevolution = usbGetRotationalPeriod(); + std::cerr << fmt::format("{}ms\n", _oneRevolution / 1e6); } ~HardwareFluxSource() @@ -40,9 +50,10 @@ class HardwareFluxSource : public FluxSource { usbSetDrive(_drive, high_density, indexMode); usbSeek(track); - Bytes crunched = usbRead(side, revolutions); + Bytes crunched = usbRead(side, synced, revolutions * _oneRevolution); auto fluxmap = std::make_unique(); fluxmap->appendBytes(crunched.uncrunch()); + std::cerr << "return fluxmap\n"; return fluxmap; } @@ -59,13 +70,19 @@ class HardwareFluxSource : public FluxSource private: unsigned _drive; unsigned _revolutions; + nanoseconds_t _oneRevolution; }; -void setHardwareFluxSourceRevolutions(int revolutions) +void setHardwareFluxSourceRevolutions(double revolutions) { ::revolutions.setDefaultValue(revolutions); } +void setHardwareFluxSourceSynced(bool synced) +{ + ::synced.setDefaultValue(synced); +} + std::unique_ptr FluxSource::createHardwareFluxSource(unsigned drive) { return std::unique_ptr(new HardwareFluxSource(drive)); diff --git a/lib/usb.cc b/lib/usb.cc index 440ac6b6..621b6c6d 100644 --- a/lib/usb.cc +++ b/lib/usb.cc @@ -149,7 +149,7 @@ nanoseconds_t usbGetRotationalPeriod(void) usb_cmd_send(&f, f.f.size); auto r = await_reply(F_FRAME_MEASURE_SPEED_REPLY); - return r->period_ms * 1000; + return r->period_ms * 1000000; } static int large_bulk_transfer(int ep, Bytes& bytes) @@ -202,13 +202,16 @@ void usbTestBulkTransport() await_reply(F_FRAME_BULK_TEST_REPLY); } -Bytes usbRead(int side, int revolutions) +Bytes usbRead(int side, bool synced, nanoseconds_t readTime) { struct read_frame f = { .f = { .type = F_FRAME_READ_CMD, .size = sizeof(f) }, .side = (uint8_t) side, - .revolutions = (uint8_t) revolutions + .synced = (uint8_t) synced }; + uint16_t milliseconds = readTime / 1e6; + ((uint8_t*)&f.milliseconds)[0] = milliseconds; + ((uint8_t*)&f.milliseconds)[1] = milliseconds >> 8; usb_cmd_send(&f, f.f.size); auto fluxmap = std::unique_ptr(new Fluxmap); diff --git a/lib/usb.h b/lib/usb.h index 16941bb2..458a35bf 100644 --- a/lib/usb.h +++ b/lib/usb.h @@ -9,7 +9,7 @@ extern void usbRecalibrate(); extern void usbSeek(int track); extern nanoseconds_t usbGetRotationalPeriod(); extern void usbTestBulkTransport(); -extern Bytes usbRead(int side, int revolutions); +extern Bytes usbRead(int side, bool synced, nanoseconds_t readTime); extern void usbWrite(int side, const Bytes& bytes); extern void usbErase(int side); extern void usbSetDrive(int drive, bool high_density, int index_mode); diff --git a/protocol.h b/protocol.h index 7e301799..de7c257e 100644 --- a/protocol.h +++ b/protocol.h @@ -3,7 +3,7 @@ enum { - FLUXENGINE_VERSION = 10, + FLUXENGINE_VERSION = 11, FLUXENGINE_VID = 0x1209, FLUXENGINE_PID = 0x6e00, @@ -133,7 +133,8 @@ struct read_frame { struct frame_header f; uint8_t side; - uint8_t revolutions; + uint8_t synced; + uint16_t milliseconds; }; struct write_frame diff --git a/src/fe-rpm.cc b/src/fe-rpm.cc index 0b12d473..aa2ea428 100644 --- a/src/fe-rpm.cc +++ b/src/fe-rpm.cc @@ -19,7 +19,7 @@ int mainRpm(int argc, const char* argv[]) usbSetDrive(spec.drive, false, F_INDEX_REAL); nanoseconds_t period = usbGetRotationalPeriod(); if (period != 0) - std::cout << "Rotational period is " << period/1000 << " ms (" << 60e6/period << " rpm)" << std::endl; + std::cout << "Rotational period is " << period/1000000 << " ms (" << 60e3/period << " rpm)" << std::endl; else { std::cout << "No index pulses detected from the disk. Common causes of this are:\n"