{"action":"created","issue":{"url":"https://api.github.com/repos/roboterclubaachen/xpcc/issues/17","labels_url":"https://api.github.com/repos/roboterclubaachen/xpcc/issues/17/labels{/name}","comments_url":"https://api.github.com/repos/roboterclubaachen/xpcc/issues/17/comments","events_url":"https://api.github.com/repos/roboterclubaachen/xpcc/issues/17/events","html_url":"https://github.com/roboterclubaachen/xpcc/issues/17","id":55845957,"number":17,"title":"extend xpcc::Timestamp to 32bit","user":{"login":"daniel-k","id":224128,"avatar_url":"https://avatars.githubusercontent.com/u/224128?v=3","gravatar_id":"","url":"https://api.github.com/users/daniel-k","html_url":"https://github.com/daniel-k","followers_url":"https://api.github.com/users/daniel-k/followers","following_url":"https://api.github.com/users/daniel-k/following{/other_user}","gists_url":"https://api.github.com/users/daniel-k/gists{/gist_id}","starred_url":"https://api.github.com/users/daniel-k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/daniel-k/subscriptions","organizations_url":"https://api.github.com/users/daniel-k/orgs","repos_url":"https://api.github.com/users/daniel-k/repos","events_url":"https://api.github.com/users/daniel-k/events{/privacy}","received_events_url":"https://api.github.com/users/daniel-k/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":5,"created_at":"2015-01-29T02:05:35Z","updated_at":"2015-02-08T15:18:15Z","closed_at":null,"body":"At the moment xpcc::Timestamp is of type uint_fast16_t. This limits in particular the usage of xpcc::Timeout to approx. 65 seconds. I have a use case where I need bigger intervals.\r\n\r\nThe questions is now why 16bit was choosen in particular. As software timeouts and timers are not suitable for time critical applications anyway, I wonder if this could safely be increased to 32bit.\r\n\r\n\r\nFor the moment I can work around this, but having 32bit timestamps would be really nice."},"comment":{"url":"https://api.github.com/repos/roboterclubaachen/xpcc/issues/comments/73415034","html_url":"https://github.com/roboterclubaachen/xpcc/issues/17#issuecomment-73415034","issue_url":"https://api.github.com/repos/roboterclubaachen/xpcc/issues/17","id":73415034,"user":{"login":"salkinium","id":163066,"avatar_url":"https://avatars.githubusercontent.com/u/163066?v=3","gravatar_id":"","url":"https://api.github.com/users/salkinium","html_url":"https://github.com/salkinium","followers_url":"https://api.github.com/users/salkinium/followers","following_url":"https://api.github.com/users/salkinium/following{/other_user}","gists_url":"https://api.github.com/users/salkinium/gists{/gist_id}","starred_url":"https://api.github.com/users/salkinium/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/salkinium/subscriptions","organizations_url":"https://api.github.com/users/salkinium/orgs","repos_url":"https://api.github.com/users/salkinium/repos","events_url":"https://api.github.com/users/salkinium/events{/privacy}","received_events_url":"https://api.github.com/users/salkinium/received_events","type":"User","site_admin":false},"created_at":"2015-02-08T15:18:15Z","updated_at":"2015-02-08T15:18:15Z","body":"Ok, so I looked at the generated ASM on the AVR8 core of the (modern) ATmega328p for incrementing a uint8_t vs. uint16_t vs. uint32_t value by a constant (of 1).\r\nI annotated the ASM with the instruction description and number of required clock cycles.\r\n\r\nMy observations:\r\n\r\n0. AVRs don't have a ADDI (Add Constant to Register) for uint8_t, they can use SUBI (Subtract Constant from Register) with arithmetic underflow.\r\n1. The time it takes is uint32_t = uint16_t *2 = uint8_t * 4. Nice.\r\n2. The amount of registers used is uint32_t = uint16_t *2 = uint8_t * 4. Not really a surprise.\r\n3. The code size is actually a little better: uint16_t < uint8_t * 2 and uint32_t < uint8_t * 4.\r\n4. The main impact on timing and code size is the moving of the values between SRAM and registers.\r\nThe arithmetic operations are not actually that expensive.\r\n\r\nI therefore suggest we move forward and give `xpcc::Clock` a uint32_t value to increment, as this is only 10 clock cycles more per increment (or 10.000 cycles more per second at 1ms resolution).\r\n\r\nWe should however provide two timer implementations as @ekiwi suggested, to optimize the access times and code size of all classes using `xpcc::Timeout`.\r\n\r\n@dergraaf\r\nWhat is the rational behind the template parameter in `xpcc::Timeout`, `xpcc::PeriodicTimer`?\r\nWhy/when would you have multiple `xpcc::Clock` instances in your project?\r\n\r\n~~~\r\n// volatile uint8_t clock;\r\n// clock++\r\n8a:\t80 91 00 01 \tlds\tr24, 0x0100\t\t\t\t// Load Direct from SRAM: 2 clocks\r\n8e:\t8f 5f       \tsubi\tr24, 0xFF\t; 255\t// Subtract Constant from Register: 1 clock (x-255 == x+1 with 8bit underflow)\r\n90:\t80 93 00 01 \tsts\t0x0100, r24\t\t\t\t// Store Direct to SRAM: 2 clocks\r\n// Total time: 5 clocks, 4 clocks load/store, 1 clock arithmetic\r\n// Total size: 10B instructions, 8 load/store, 2 arithmetic, + 1 register\r\n\r\n// volatile uint16_t clock;\r\n// clock++\r\n8a:\t80 91 00 01 \tlds\tr24, 0x0100\t\t\t\t// Load Direct from SRAM: 2 clocks\r\n8e:\t90 91 01 01 \tlds\tr25, 0x0101\t\t\t\t// Load Direct from SRAM: 2 clocks\r\n92:\t01 96       \tadiw\tr24, 0x01\t; 1\t\t// Add Immediate to Word: 2 clocks\r\n94:\t90 93 01 01 \tsts\t0x0101, r25\t\t\t\t// Store Direct to SRAM: 2 clocks\r\n98:\t80 93 00 01 \tsts\t0x0100, r24\t\t\t\t// Store Direct to SRAM: 2 clocks\r\n// Total time: 10 clocks, 8 clocks load/store, 2 clocks arithmetic\r\n// Total size: 18B instructions, 16 load/store, 2 arithmetic, + 2 registers\r\n\r\n// volatile uint32_t clock;\r\n// clock++\r\n8a:\t80 91 00 01 \tlds\tr24, 0x0100\t\t\t\t// Load Direct from SRAM: 2 clocks\r\n8e:\t90 91 01 01 \tlds\tr25, 0x0101\t\t\t\t// Load Direct from SRAM: 2 clocks\r\n92:\ta0 91 02 01 \tlds\tr26, 0x0102\t\t\t\t// Load Direct from SRAM: 2 clocks\r\n96:\tb0 91 03 01 \tlds\tr27, 0x0103\t\t\t\t// Load Direct from SRAM: 2 clocks\r\n9a:\t01 96       \tadiw\tr24, 0x01\t; 1\t\t// Add Immediate to Word: 2 clocks\r\n9c:\ta1 1d       \tadc\tr26, r1\t\t\t\t\t// Add with Carry two Registers: 1 clock\r\n9e:\tb1 1d       \tadc\tr27, r1\t\t\t\t\t// Add with Carry two Registers: 1 clock\r\na0:\t80 93 00 01 \tsts\t0x0100, r24\t\t\t\t// Store Direct to SRAM: 2 clocks\r\na4:\t90 93 01 01 \tsts\t0x0101, r25\t\t\t\t// Store Direct to SRAM: 2 clocks\r\na8:\ta0 93 02 01 \tsts\t0x0102, r26\t\t\t\t// Store Direct to SRAM: 2 clocks\r\nac:\tb0 93 03 01 \tsts\t0x0103, r27\t\t\t\t// Store Direct to SRAM: 2 clocks\r\n// Total time: 20 clocks, 16 clocks load/store, 4 clock arithmetic\r\n// Total size: 38B instructions, 32 load/store, 6 arithmetic, +  4 registers\r\n~~~"}}