{"id":240,"date":"2011-09-29T18:03:07","date_gmt":"2011-09-29T18:03:07","guid":{"rendered":"http:\/\/41j.com\/blog\/?p=240"},"modified":"2011-09-29T23:30:24","modified_gmt":"2011-09-29T23:30:24","slug":"msp430-with-3310-nokia-lcd","status":"publish","type":"post","link":"https:\/\/41j.com\/blog\/2011\/09\/msp430-with-3310-nokia-lcd\/","title":{"rendered":"MSP430 2013 with 3310 Nokia LCD"},"content":{"rendered":"<p>I&#8217;ve started playing with the Nokia 3310 LCD. It&#8217;s similar to the LCD I used in my <a href=\"http:\/\/41j.com\/blog\/2011\/09\/msp430-watch\/\">watch project<\/a> but is black and white only. It&#8217;s a little clearer to read, and hopefully consumes less power.<\/p>\n<p>I&#8217;d ordered a pack of 7 nokia 3310 LCDs from the internet. However after I disassembled the nokia packaging I noticed there were actually 3 different LCD types present:<\/p>\n<p><a href=\"http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_types.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_types-1024x327.jpg\" alt=\"\" title=\"3310lcd_types\" width=\"630\" height=\"201\" class=\"aligncenter size-large wp-image-252\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_types-1024x327.jpg 1024w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_types-300x96.jpg 300w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_types.jpg 1187w\" sizes=\"auto, (max-width: 630px) 100vw, 630px\" \/><\/a><\/p>\n<p>One didn&#8217;t have metal contacts, only glass ones. The other, with the smaller IC I spent a long time fiddling with, and couldn&#8217;t get anything to display on. It could be that my wiring was dodgy but I&#8217;ve also known LCDs for the same phone to behave differently. Nokia have been known to use different LCDs in their phones and include detection logic to figure out how to  drive it. Anyway&#8230; the LCD with the larger controller worked, and if you are considering using a 3310 display I&#8217;d recommend you try and find this type.<\/p>\n<p>I used the code from <a href=\"http:\/\/tophathacker.com\/?p=40\">here<\/a> as my basis. I removed a lot of his project specific logic and added my own simple test code.<\/p>\n<p>Here&#8217;s the setup:<\/p>\n<p><a href=\"http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_setup.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_setup-1024x879.jpg\" alt=\"\" title=\"3310lcd_setup\" width=\"630\" height=\"540\" class=\"aligncenter size-large wp-image-253\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_setup-1024x879.jpg 1024w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_setup-300x257.jpg 300w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_setup.jpg 1903w\" sizes=\"auto, (max-width: 630px) 100vw, 630px\" \/><\/a><\/p>\n<p>That cap does seem to be required. The 3510i LCD works without one, I might do some more experimentation with this.<\/p>\n<p>And here&#8217;s what the code outputs:<\/p>\n<p><a href=\"http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_demo.jpg\"><img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_demo-1024x936.jpg\" alt=\"\" title=\"3310lcd_demo\" width=\"630\" height=\"575\" class=\"aligncenter size-large wp-image-254\" srcset=\"https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_demo-1024x936.jpg 1024w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_demo-300x274.jpg 300w, https:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/3310lcd_demo.jpg 1239w\" sizes=\"auto, (max-width: 630px) 100vw, 630px\" \/><\/a><\/p>\n<p>And here&#8217;s the code! Again, largely due to TopHatHacker, with some trimming down and a few modifications:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n#define F_CPU 1000000UL\r\n\r\n#include &lt;io.h&gt;\r\n#include &lt;signal.h&gt;\r\n\r\n#define SEND_CMD                   0\r\n#define SEND_CHR                   1\r\n\r\n#define LCD_X_RES                  84\r\n#define LCD_Y_RES                  48\r\n\r\n#define COUNTDOWN\t\t\t\t   1\r\n\r\n\/\/ defines for 4250 pin connections to Nokia 3310\r\n#define SCEPORT P1OUT \r\n#define SDINPORT P1OUT\r\n#define DCPORT P1OUT\r\n#define SCKPORT P1OUT\r\n#define RESPORT P1OUT\r\n#define SCE  BIT5 \/\/ LCD pin 5 (enable)\r\n#define SDIN BIT3 \/\/ LCD pin 3 (data)\r\n#define DC   BIT4 \/\/ LCD pin 4 (Data enabled)\r\n#define SCK  BIT1 \/\/ LCD pin 2 (Data clock)\r\n#define RES  BIT2 \/\/ LCD pin 8 (reset)\r\n\r\nvoid LCDSend(unsigned char,unsigned char);\r\nvoid LCDClear(void);\r\nvoid LCDInit(void);\r\nvoid LCDBlack(void);\r\nvoid LCDCurs(unsigned char,unsigned char);\r\n\r\nvoid LCDSend(unsigned char data, unsigned char cd) {\r\n\r\n  volatile unsigned char bits;\r\n  unsigned short cnt=8;\r\n  \/\/ assume clk is hi\r\n  \/\/ Enable display controller (active low).\r\n  SCEPORT &amp;amp;amp;amp;amp;= ~SCE;  \/\/RESET SCE\r\n\r\n  \/\/ command or data\r\n  if(cd == SEND_CHR) {\r\n    DCPORT |= DC;  \/\/set to send data\r\n  }\r\n  else {  \/\/ reset to send command\r\n    DCPORT &amp;amp;amp;amp;amp;= ~DC;\r\n  }\r\n\r\n  \/\/\/\/\/ SEND SPI \/\/\/\/\/\r\n  bits=0x80; \/\/ bits is mask to select bit to send. select bit msb first\r\n \r\n  \/\/send data\r\n  while (0&lt;cnt--)\r\n  {\r\n    \/\/ put bit on line\r\n    \/\/ cycle clock\r\n    SCKPORT &amp;amp;amp;amp;amp;= ~SCK;\r\n    if ((data &amp;amp;amp;amp;amp; bits)&gt;0) SDINPORT |= SDIN; else SDINPORT &amp;amp;amp;amp;amp;= ~SDIN;\r\n    \/\/Delay(1);\r\n    SCKPORT |= SCK;\r\n    \/\/Delay(2);\r\n    \/\/ SHIFT BIT MASK 1 right\r\n    bits &gt;&gt;= 1;\r\n  }\r\n   \r\n  \/\/ Disable display controller.\r\n  SCEPORT |= SCE;\r\n\r\n}\r\n\r\nvoid LCDClear(void) {\r\n  int i,j;\r\n      \r\n  LCDSend(0x80, SEND_CMD );\r\n  LCDSend(0x40, SEND_CMD );\r\n  \r\n  for (i=0;i&lt;6;i++)  \/\/ number of rows\r\n    for (j=0;j&lt;LCD_X_RES;j++)  \/\/ number of columns\r\n      LCDSend(0x00, SEND_CHR);\r\n}\r\n\r\nvoid LCDInit(void)\r\n{ \/\/ assume ports set up and initialized to output\r\n\r\n  \/\/ Reset LCD\r\n  SCEPORT &amp;amp;amp;amp;amp;= ~SCE;          \/\/ RESET SCE to enable \r\n  \/\/ toggle RES\r\n  RESPORT |= RES;           \/\/ Set RES\r\n  char l;\r\n  for(l=0;l&lt;100;l++)\r\n    l=l;\r\n  RESPORT &amp;amp;amp;amp;amp;= ~RES;          \/\/ reset RES\r\n  for(l=0;l&lt;100;l++)\r\n    l=l;\r\n  RESPORT |= RES;           \/\/ Set RES\r\n  \r\n  \/\/ Cycle Clock\r\n  SCKPORT &amp;amp;amp;amp;amp;= ~SCK;\r\n  SCKPORT |= SCK;\r\n \r\n \/\/ Disable display controller.\r\n  SCEPORT |= SCE;           \/\/ bring high to disable \r\n  \r\n  for(l=0;l&lt;100;l++)\r\n    l=l;\r\n\r\n  \/\/ Send sequence of command\r\n  LCDSend( 0x21, SEND_CMD );  \/\/ LCD Extended Commands.\r\n  LCDSend( 0xC8, SEND_CMD );  \/\/ Set LCD Vop (Contrast).\r\n  LCDSend( 0x06, SEND_CMD );  \/\/ Set Temp coefficent to 2.\r\n  LCDSend( 0x13, SEND_CMD );  \/\/ LCD bias mode 1:100.\r\n  LCDSend( 0x20, SEND_CMD );  \/\/ LCD Standard Commands, Horizontal addressing mode.\r\n  LCDSend( 0x08, SEND_CMD );  \/\/ LCD blank\r\n  LCDSend( 0x0C, SEND_CMD );  \/\/ LCD in inverse mode.\r\n  \r\n  LCDClear();\r\n\r\n}\r\n\r\nvoid lcdcontrast(char c) {\r\n  LCDSend( 0x21, SEND_CMD );  \/\/ LCD Extended Commands.\r\n  LCDSend( c, SEND_CMD );  \/\/ Set LCD Vop (Contrast).\r\n  LCDSend( 0x20, SEND_CMD );  \/\/ LCD Standard Commands, Horizontal addressing mode.\r\n}\r\n\r\nvoid LCDCurs(unsigned char x, unsigned char y)\r\n{\r\n\tLCDSend(0x80|x,SEND_CMD);\r\n\tLCDSend(0x40|y,SEND_CMD);\r\n}\r\n\r\nvoid LCDDot()\r\n{\r\n  int lm;\r\n  LCDSend(0x00,SEND_CHR);\r\n  LCDSend(0x00,SEND_CHR);\r\n  LCDSend(0x00,SEND_CHR);\r\n  for(lm=0;lm&lt;3;lm++)\r\n    LCDSend(0xFF,SEND_CHR);\r\n}\r\n\r\nint main(void)\r\n{\r\n  WDTCTL = WDTPW + WDTHOLD;\t\/\/ Stop WDT\r\n  P1DIR = 0xFF;\r\n  \r\n  BCSCTL1 = CALBC1_1MHZ;                   \/\/ Set range\r\n  DCOCTL = CALDCO_1MHZ;                    \/\/ Set DCO step + modulation\r\n  \r\n  BCSCTL2 = 0xF8;\r\n  BCSCTL3 = LFXT1S_0 + XCAP_3;\r\n  \r\n  CCTL0 = CCIE;\r\n  CCR0 = 0;\r\n  TACCR0 = 0x3FF;\r\n  TACTL = 0x0211;\r\n  \r\n  LCDInit();\r\n  \r\n  _BIS_SR(GIE);\r\n\r\n  \/\/ draw cross pattern\r\n  char v = 0xAA;\r\n  for(int x=0;x&lt;((84*48)\/8);x++) {\r\n    LCDSend(v,SEND_CHR);\r\n    v = v ^ 0xFF;\r\n  }\r\n  for(;;);\r\n}\r\n&amp;#91;\/sourcecode&amp;#93;\r\n\r\n&lt;h2&gt;Notes&lt;\/h2&gt;\r\n\r\nMSP430 pinout:\r\n\r\n&lt;a href=&quot;http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/MSP430F2011-pinout.jpg&quot;&gt;&lt;img src=&quot;http:\/\/41j.com\/blog\/wp-content\/uploads\/2011\/09\/MSP430F2011-pinout.jpg&quot; alt=&quot;&quot; title=&quot;MSP430F2011-pinout&quot; width=&quot;398&quot; height=&quot;129&quot; class=&quot;aligncenter size-full wp-image-241&quot; \/&gt;&lt;\/a&gt;\r\n\r\nLCD pinout and AVR code &lt;a href=&quot;http:\/\/www.quantumtorque.com\/content\/view\/32\/37\/&quot;&gt;here&lt;\/a&gt;.\r\n\r\nOther 3310 projects:\r\n\r\nWith a larger MSP430: &lt;a href=&quot;http:\/\/tophathacker.com\/?p=40&quot;&gt;here&lt;\/a&gt; and &lt;a href=&quot;http:\/\/320volt.com\/msp430-nokia-3310-lcd-direnc-hesaplayici-yeniden\/&quot;&gt;here&lt;\/a&gt;\r\n\r\nVarious nokia LCD pinouts &lt;a href=&quot;http:\/\/www.module.ro\/nokia_3510.html&quot;&gt;here&lt;\/a&gt;\r\n\r\nThe code is compiled as:\r\n\r\n&#x5B;sourcecode language=&quot;bash&quot;]\r\n~\/msp430\/bin\/msp430-gcc -Os -Wall -mmcu=msp430x2013 -std=gnu99 -o main.elf main.o \r\n<\/pre>\n<p>MSPDebug is used to  program the device. run as:<\/p>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\nmspdebug uif -d \/dev\/ttyUSB0\r\n<\/pre>\n<p>MSPDebug is launched type: prog main.elf to program, run to run.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve started playing with the Nokia 3310 LCD. It&#8217;s similar to the LCD I used in my watch project but is black and white only. It&#8217;s a little clearer to read, and hopefully consumes less power. I&#8217;d ordered a pack of 7 nokia 3310 LCDs from the internet. However after I disassembled the nokia packaging [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1],"tags":[],"class_list":["post-240","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p1RRoU-3S","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/240","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/comments?post=240"}],"version-history":[{"count":15,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/240\/revisions"}],"predecessor-version":[{"id":261,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/posts\/240\/revisions\/261"}],"wp:attachment":[{"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/media?parent=240"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/categories?post=240"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/41j.com\/blog\/wp-json\/wp\/v2\/tags?post=240"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}