{"id":715,"date":"2015-12-22T22:05:18","date_gmt":"2015-12-22T21:05:18","guid":{"rendered":"https:\/\/www.livediesel.de\/?p=715"},"modified":"2015-12-22T22:05:18","modified_gmt":"2015-12-22T21:05:18","slug":"increase-msp432-spi-performance-part-1","status":"publish","type":"post","link":"https:\/\/www.livediesel.de\/?p=715","title":{"rendered":"Increase MSP432\u2122 SPI Performance &#8211; Part 1"},"content":{"rendered":"<p>Currently I work on a 240&#215;320 Pixel QVGA Display, connected via\u00a0SPI. As\u00a0I wrote this article I mentioned this was a bad idea.<\/p>\n<p>Following calculation:<\/p>\n<ul>\n<li>240 x 320 Pixel =\u00a076.800 Pixel<\/li>\n<li>16 Bit (Color Mode) * 76.800 Pixel =\u00a01.228.800 Bit<\/li>\n<li>MSP432P401R SPI max frequency = 24MHz<\/li>\n<li>24.000.000 \/ 1.228.800 =\u00a019,53125<\/li>\n<\/ul>\n<p>This makes a maximum Full Screen FPS of round about 20. So for the human eye it is to slow.<\/p>\n<p>Ok, for now I can&#8217;t break this limit, but I can try to reach it.<\/p>\n<h3>Try One: use eUSCI ISR handler<\/h3>\n<pre lang=\"c\">void UCIA0IsrHandler(void)\r\n{\r\n    switch(UCIA0IV)\r\n    {\r\n    case 0x0004: \/\/ UCTXIFG\r\n        if (fill_count & 0x001)\r\n        {\r\n            UCIA0TXBUF = fill_data_h;\r\n        }\r\n        else\r\n        {\r\n            UCIA0TXBUF = fill_data_l;\r\n        }\r\n        fill_count--;\r\n\r\n        if (fill_count)\r\n        {\r\n            return;\r\n        }\r\n\r\n        UCIA0IE &= ~(UCTXIE);\r\n        break;\r\n    }\r\n}\r\n<\/pre>\n<p>Whats the result of this: a bad one. I tried to count the CPU steps until the new byte is pushed to the transmit buffer.<\/p>\n<p>The Disassembler shows 14 steps, I think with ISR Join and Leave I&#8217;m over 16, which results in a gap between each byte and the transmission is slower than 20 fps.<\/p>\n<p>There are possibilities to optimize this code, but for me are 16 steps between ISRs too few.<\/p>\n<h3>Try Two: Synchronized transmission<\/h3>\n<pre lang=\"c\">#define SendSync(data) \\\r\n    UCIA0TXBUF = data; \\\r\n    while (UCIA0STAT & UCBUSY);\r\n\r\nvoid Fill(uint16_t color, uint32_t count32)\r\n{\r\n    uint8_t a = color >> 8;\r\n    uint8_t b = color;\r\n    \r\n    uint8_t slow = count32 & 0x07;\r\n    if (slow)\r\n    {\r\n        do {\r\n            SendSync(a);\r\n            SendSync(b);\r\n        } while (--slow);\r\n    }\r\n\r\n    \/\/ x8 unrolled\r\n    int count = count32 >> 3;\r\n    if (count)\r\n    {\r\n        do {\r\n            SendSync(a);\r\n            SendSync(b);\r\n\r\n            SendSync(a);\r\n            SendSync(b);\r\n\r\n            SendSync(a);\r\n            SendSync(b);\r\n\r\n            SendSync(a);\r\n            SendSync(b);\r\n\r\n            SendSync(a);\r\n            SendSync(b);\r\n\r\n            SendSync(a);\r\n            SendSync(b);\r\n\r\n            SendSync(a);\r\n            SendSync(b);\r\n\r\n            SendSync(a);\r\n            SendSync(b);\r\n        } while (--count);\r\n    }\r\n}\r\n<\/pre>\n<p>This results in 8 Steps for each byte and with a bit logic you reach the 20 fps.<br \/>\nWhat comes next?, decrease the code size. This can be done using Assembler.<br \/>\nThe next part, I hope will contain the Fill function in asm.<\/p>\n<h3>First summary<\/h3>\n<p>At first I would say: what the heck, (TI) you build a 32Bit ARM Core based on MSP430 but there is only a 8Bit SPI Interface. Why don&#8217;t use in addition a transfer mask, that makes it variable in how meany bits to\u00a0transfer. In my case I could set a 16bit mask until the data can be divided by two and then I can ship 32bit data.<\/p>\n<p>This could make the use of ISR more efficient, because this creates a gap of 64 CPU Steps, which are enough to do other stuff.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Currently I work on a 240&#215;320 Pixel QVGA Display, connected via\u00a0SPI. As\u00a0I wrote this article I mentioned this was a bad idea. Following calculation: 240 x 320 Pixel =\u00a076.800 Pixel 16 Bit (Color Mode) * 76.800 Pixel =\u00a01.228.800 Bit MSP432P401R SPI max frequency = 24MHz 24.000.000 \/ 1.228.800 =\u00a019,53125 This makes a maximum Full Screen [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[21,64,13],"tags":[75,52,65,67,59],"class_list":["post-715","post","type-post","status-publish","format-standard","hentry","category-mikrocontroller","category-msp432","category-programming","tag-display","tag-msp","tag-msp432","tag-msp432p401r","tag-spi"],"_links":{"self":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts\/715","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=715"}],"version-history":[{"count":12,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts\/715\/revisions"}],"predecessor-version":[{"id":727,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=\/wp\/v2\/posts\/715\/revisions\/727"}],"wp:attachment":[{"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=715"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=715"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.livediesel.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=715"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}